Main Page | Modules | Alphabetical List | Compound List | File List | Compound Members | Related Pages

turing_machine.hpp

00001 #ifndef ross_turing_machine_header
00002 #define ross_turing_machine_header
00003 
00004 /*Authored 2002    by  Kyle  Ross,  Undergraduate  Philosophy   Thesis
00005 (Advisor: Professor Bram van Heuveln)
00006 
00007 Modified 2003    by Owen Kellett, Undergraduate Research
00008 (Advisor: Professor Bram van Heuveln)
00009 
00010 This  file is part of the   "Generic Turing Machine Implementation for
00011 Use in the Exploration of the Busy Beaver Problem".
00012 
00013 The "Generic Turing Machine Implementation for  Use in the Exploration
00014 of the Busy Beaver Problem" is free  software; you can redistribute it
00015 and/or modify it under the terms of the  GNU General Public License as
00016 published   by the Free Software Foundation;   either version 2 of the
00017 License, or (at your option) any later version.
00018 
00019 This programme is distributed in the hope that it  will be useful, but
00020 WITHOUT    ANY  WARRANTY;  without   even  the    implied warranty  of
00021 MERCHANTABILITY or FITNESS FOR  A  PARTICULAR  PURPOSE.  See  the  GNU
00022 General Public License for more details.
00023 
00024 You should have received   a copy of  the  GNU General Public  License
00025 along  with  this   programme; if  not,  write   to the Free  Software
00026 Foundation, Inc., 59  Temple Place, Suite  330, Boston, MA  02111-1307
00027 USA (or visit http://www.fsf.org/licenses/licenses.html)
00028 
00029 Created as part of the Busy Beaver Project:
00030 Bram van Heuveln <heuveb@rpi.edu>
00031 Boleshaw Szymanski <szymansk@cs.rpi.edu>
00032 Selmer Bringsjord <selmer@rpi.edu>
00033 Carlos Varela <cvarela@cs.rpi.edu>
00034 Owen Kellett <kelleo@rpi.edu>
00035 Shailesh Kelkar <kelkas@rpi.edu>
00036 Kyle Ross <rossk2@rpi.edu>
00037 Rensselaer Reasoning Group
00038 Department of Cognitive Science
00039 Department of Computer Science
00040 Rensselaer Polytechnic Institute
00041 Troy, New York 12180
00042 U.S.A.
00043 */
00044 //implements a five-tuple turing machine (and can simulate a four-tuple turing machine) over an arbitrary (small) alphabet
00045 
00046 #define enableLoggingOutput
00047 #define enable_optimisations
00048 #define blank_tape_optimisation
00049 #define no_ss_optimisation
00050 #define no_ssprime_sprimes_optimisation
00051 #define first_write_optimisation
00052 #define first_move_optimisation
00053 
00054 void display_optimisation_settings(std::ostream &out)
00055 {
00056         #ifdef enable_optimisations
00057                 out<<"optimisations enabled:"<<std::endl;
00058                 out<<" blank-tape-optimisation: ";
00059                 #ifdef blank_tape_optimisation
00060                         out<<"on"<<std::endl;
00061                 #else
00062                         out<<"off"<<std::endl;
00063                 #endif
00064                 out<<" no-ss-optimisation: ";
00065                 #ifdef no_ss_optimisation
00066                         out<<"on"<<std::endl;
00067                 #else
00068                         out<<"off"<<std::endl;
00069                 #endif
00070                 out<<" no-ssprime-sprimes-optimisation: ";
00071                 #ifdef no_ssprime_sprimes_optimisation
00072                         out<<"on"<<std::endl;
00073                 #else
00074                         out<<"off"<<std::endl;
00075                 #endif
00076                 out<<" first-write-optimisation: ";
00077                 #ifdef first_write_optimisation
00078                         out<<"on"<<std::endl;
00079                 #else
00080                         out<<"off"<<std::endl;
00081                 #endif
00082                 out<<" first-move-optimisation: ";
00083                 #ifdef first_move_optimisation
00084                         #ifndef first_write_optimisation
00085                                 out<<"disabled because first-write is not on"<<std::endl;
00086                         #else
00087                                 out<<"on"<<std::endl;
00088                         #endif
00089                 #else
00090                         out<<"off"<<std::endl;
00091                 #endif
00092         #else
00093                 out<<"optimisations disabled"<<std::endl;
00094         #endif
00095 }
00096 
00097 #include <cmath>
00098 #include <vector>
00099 #include "debug.hpp"
00100 #include "infinite_tape.hpp"
00101 #include "state.hpp"
00102 #include "machine_storage.hpp"
00103 #include "watch.hpp"
00104 template <typename T>
00105 T& last_element(std::vector<T> &the_list);
00106 
00111 template <typename T>
00112 class turing_machine
00113 {
00114 public:
00115         typedef typename std::vector<state<T> >::size_type transition_index_type;
00116         typedef typename infinite_tape<T>::direction move_type;
00117         typedef typename state<T>::transition_result result_type;
00118         typedef unsigned long int transition_count_type;
00119         static const move_type left=infinite_tape<T>::left;
00120         static const move_type right=infinite_tape<T>::right;
00121         static const move_type do_nothing=infinite_tape<T>::do_nothing;
00122         static const move_type halt_move=infinite_tape<T>::halt_move;
00123         static const result_type run=state<T>::run;
00124         static const result_type halt=state<T>::halt;
00125 
00133         turing_machine(const turing_machine<T> &rhs)
00134         :current(rhs.current), transition_function(rhs.transition_function), tape(rhs.tape), steps(rhs.steps), run_status(rhs.run_status), halt_state(rhs.halt_state), halt_state_exists(rhs.halt_state_exists), first_unreachable_state(rhs.first_unreachable_state)
00135         {
00136                 #ifdef ross_debug_mode
00137                         std::cout<<"["<<this<<"]turing-machine copy-constructed"<<std::endl;
00138                 #endif
00139         }
00140 
00148         turing_machine(T default_tape_value)
00149         :tape(default_tape_value), current(0), steps(0), run_status(run), halt_state_exists(false), first_unreachable_state(1)
00150         {
00151                 #ifdef ross_debug_mode
00152                         std::cout<<"["<<this<<"]turing-machine constructed"<<std::endl;
00153                 #endif
00154         }
00155 
00164         turing_machine(transition_index_type N, T default_tape_value)
00165         :tape(default_tape_value), current(0), transition_function(N), steps(0), run_status(run), halt_state_exists(false), first_unreachable_state(1)
00166         {
00167                 #ifdef ross_debug_mode
00168                         std::cout<<"["<<this<<"]turing-machine constructed"<<std::endl;
00169                 #endif
00170         }
00171 
00179         turing_machine(const infinite_tape<T> &new_tape)
00180         :tape(new_tape), current(0), steps(0), run_status(run), halt_state_exists(false), first_unreachable_state(1)
00181         {
00182                 #ifdef ross_debug_mode
00183                         std::cout<<"["<<this<<"]turing-machine constructed"<<std::endl;
00184                 #endif
00185         }
00186 
00191         ~turing_machine()
00192         {
00193                 #ifdef ross_debug_mode
00194                         std::cout<<"["<<this<<"]turing-machine destroyed"<<std::endl;
00195                 #endif
00196         }
00197 
00205         transition_index_type add_state()
00206         {
00207                 transition_function.push_back(state<T>()); //calling the default constructor to create an anonymous object each time might be more overhead than having a static default state<T>() stored, but I'm not going to worry about this since add_state calls' cost should be trivial compared to running the TM
00208                 return transition_function.size();
00209         }
00210 
00217         bool set_halt_state(transition_index_type new_halt_state)
00218         {
00219                 if(halt_state_exists)
00220                 {
00221                         #ifdef ross_debug_mode
00222                                 std::cout<<"["<<this<<"] could not set halt state since one already exists"<<std::endl;
00223                         #endif
00224                         return false;
00225                 }
00226                 else
00227                 {
00228                         if(bounds_check(new_halt_state))
00229                         {
00230                                 halt_state_exists=true;
00231                                 halt_state=new_halt_state;
00232                                 #ifdef ross_debug_mode
00233                                         std::cout<<"["<<this<<"] halt state set successfully"<<std::endl;
00234                                 #endif
00235                                 return true;
00236                         }
00237                         else
00238                         {
00239                                 #ifdef ross_debug_mode
00240                                         std::cout<<"["<<this<<"] could not create halt state since index was invalid"<<std::endl;
00241                                 #endif
00242                                 return false;
00243                         }
00244                 }
00245         }
00246 
00258         bool add_transition(transition_index_type start_state, T read, T write, move_type move, transition_index_type end_state)
00259         {
00260                 if(bounds_check(start_state) && bounds_check(end_state)) //are both states valid?
00261                 {
00262                         #ifdef ross_debug_mode
00263                                 std::cout<<"["<<this<<"]turing-machine::add-transition to state "<<start_state<<std::endl;
00264                         #endif
00265                         transition_function[start_state].create_transition(read, write, end_state, move);
00266                         if(end_state!=halt_state && end_state>=first_unreachable_state)
00267                         {
00268                                 first_unreachable_state=end_state+1;
00269                         }
00270                         return true;
00271                 }
00272                 else
00273                 {
00274                         #ifdef ross_debug_mode
00275                                 std::cout<<"["<<this<<"]turing-machine::add-transition WARNING transition not added because of bounds-check failure"<<std::endl;
00276                         #endif
00277                         return false;
00278                 }
00279         }
00280 
00291         bool add_write_transition(transition_index_type start_state, T read, T write, transition_index_type end_state)
00292         {
00293                 return add_transition(start_state, read, write, do_nothing, end_state);
00294         }
00295 
00306         bool add_move_transition(transition_index_type start_state, T read, move_type move, transition_index_type end_state)
00307         {
00308                 return add_transition(start_state, read, read, move, end_state);
00309         }
00310 
00318         bool bounds_check(transition_index_type to_check)
00319         {
00320                 return to_check<transition_function.size();
00321         }
00322 
00330         result_type run_one()
00331         {
00332                 if((run_status=transition_function[current].perform_transition(tape, current))==run)
00333                 {
00334                         ++steps;
00335                 }
00336                 if(halt_state_exists && current==halt_state)
00337                 {
00338                         run_status=halt;
00339                 }
00340                 return run_status;
00341         }
00342 
00343         //functionality for accessing the infinite_tape
00344 
00353         transition_index_type count_occurrences(T to_count) const
00354         {
00355                 return tape.count_occurrences(to_count);
00356         }
00357 
00363         const infinite_tape<T>& access_tape() const
00364         {
00365                 return tape;
00366         }
00367 
00375         infinite_tape<T>& access_tape_read_write()
00376         {
00377                 #ifdef ross_debug_mode
00378                         std::cout<<"["<<this<<"]turing-machine::access-tape-read-write WARNING this function should be used carefully"<<std::endl;
00379                 #endif
00380                 return tape;
00381         }
00382 
00389         bool in_standard_position() const
00390         {
00391                 return tape.in_standard_position();
00392         }
00393 
00399         bool blank_tape() const
00400         {
00401                 return tape.is_blank();
00402         }
00403 
00409         transition_index_type count_states() const
00410         {
00411                 return transition_function.size();
00412         }
00413 
00419         transition_index_type get_current_state() const
00420         {
00421                 return current;
00422         }
00423 
00430         result_type get_status() const
00431         {
00432                 return run_status;
00433         }
00434 
00440         transition_count_type get_steps_count() const
00441         {
00442                 return steps;
00443         }
00444 
00450         bool in_halt_state() const
00451         {
00452                 return halt_state_exists && current==halt_state;
00453         }
00454 
00460         long_int number_represented() const
00461         {
00462                 unsigned int m=0;
00463                 unsigned int n=count_states()-1;
00464 
00465                 for(typename std::vector<state<T> >::const_iterator i=transition_function.begin(); (i+1)!=transition_function.end(); ++i)
00466                 {
00467                         for(T j=0; j<=1; ++j)
00468                         {
00469                                 T write;
00470                                 typename infinite_tape<T>::direction move;
00471                                 typename std::vector<state<T> >::size_type index;
00472                                 if((*i).simulate_transition(j, write, move, index)==run)
00473                                 {
00474                                         ++m;
00475                                 }
00476                         }
00477                 }
00478 
00479                 return permutations(n-1, first_unreachable_state-1)*pow(long_int(4*n+1), long_int(2*n-m));
00480         }
00481 
00487         long_int number_represented_explicit() const
00488         {
00489                 unsigned int m=0;
00490                 unsigned int n=count_states()-1;
00491 
00492                 for(typename std::vector<state<T> >::const_iterator i=transition_function.begin(); (i+1)!=transition_function.end(); ++i)
00493                 {
00494                         for(T j=0; j<=1; ++j)
00495                         {
00496                                 T write;
00497                                 typename infinite_tape<T>::direction move;
00498                                 typename std::vector<state<T> >::size_type index;
00499                                 if((*i).simulate_transition(j, write, move, index)==run)
00500                                 {
00501                                         ++m;
00502                                 }
00503                         }
00504                 }
00505 
00506                 return permutations(n-1, first_unreachable_state-1)*pow(long_int(4*n+4), long_int(2*n-m));
00507         }
00508 
00509 
00510 
00511         //functions for output of the turing machine in various formats
00512 
00517         void print(std::ostream &out) const
00518         {
00519                 out<<tape<<std::endl;
00520                 typename std::vector<state<T> >::const_iterator i=transition_function.begin();
00521                 if(i==transition_function.end())
00522                 {
00523                         out<<"< no states exist >"<<std::endl;
00524                 }
00525                 else
00526                 {
00527                         for(int count(0); i!=transition_function.end(); ++i)
00528                         {
00529                                 out<<"state "<<(count++)<<std::endl<<(*i);
00530                         }
00531                         out<<"current state is "<<current<<std::endl;
00532                         if(halt_state_exists)
00533                         {
00534                                 out<<"halt state is "<<halt_state<<std::endl;
00535                         }
00536                         out<<"first unreachable state is "<<first_unreachable_state<<std::endl;
00537                 }
00538                 out<<"current run status is: "<<(run_status==run?"running":"halted")<<" after "<<steps<<" transitions"<<std::endl;
00539         }
00540         //functionality for tree normalisation method
00546         bool is_tn_possible() const
00547         {
00548                 if(halt_state_exists)
00549                 {
00550                         return run_status==halt && current!=halt_state;
00551                 }
00552                 else
00553                 {
00554                         return run_status==halt;
00555                 }
00556         }
00557 
00565         template <typename OutputIterator>
00566         void generate_tn_quadruple_children(const std::list<T> &alphabet, OutputIterator destination) const
00567         {
00568                 //store read symbol
00569                 T tape_symbol=tape.read();
00570 
00571                 //create a temp machine for use in generating children
00572                 turing_machine<T> temp_machine=*this;
00573 
00574                 //for each reachable (used) state:
00575                 for(transition_index_type end_state=0; end_state!=first_unreachable_state; ++end_state)
00576                 {
00577                         //for each possible write & move, create a child machine
00578                         for(typename std::list<T>::const_iterator alpha_iter=alphabet.begin(); alpha_iter!=alphabet.end(); ++alpha_iter)
00579                         {
00580                                 #ifdef no_ss_optimisation
00581                                         if((*alpha_iter)!=tape_symbol)
00582                                         {
00583                                                 temp_machine=*this;
00584                                                 temp_machine.add_write_transition(current, tape_symbol, *alpha_iter, end_state);
00585                                                 output_machine(temp_machine, destination, alphabet);
00586                                         }
00587                                         else
00588                                         {
00589                                                 temp_machine=*this;
00590                                                 temp_machine.add_write_transition(current, tape_symbol, *alpha_iter, end_state);
00591                                                 g_counter_implicit.increment(tm_stats::simple_nonproductive, temp_machine.number_represented());
00592                                                 c_counter_implicit.increment(tm_stats::simple_nonproductive, 1);
00593                                         }
00594                                 #else
00595                                                 temp_machine=*this;
00596                                                 temp_machine.add_write_transition(current, tape_symbol, *alpha_iter, end_state);
00597                                                 output_machine(temp_machine, destination, alphabet);
00598                                 #endif
00599                         }
00600 
00601                         //for each move, create a child machine
00602                         temp_machine=*this;
00603                         temp_machine.add_move_transition(current, tape_symbol, left, end_state);
00604                         output_machine(temp_machine, destination, alphabet);
00605                         temp_machine=*this;
00606                         temp_machine.add_move_transition(current, tape_symbol, right, end_state);
00607                         output_machine(temp_machine, destination, alphabet);
00608                 }
00609 
00610                 //if this machine has a halt state (which, presumably, it should!)
00611                 if(halt_state_exists)
00612                 {
00613                         //if there is an unreachable state, create transitions to it
00614                         if(first_unreachable_state!=halt_state)
00615                         {
00616                                 for(typename std::list<T>::const_iterator alpha_iter=alphabet.begin(); alpha_iter!=alphabet.end(); ++alpha_iter)
00617                                 {
00618                                         #ifdef no_ss_optimisation
00619                                                 if((*alpha_iter)!=tape_symbol)
00620                                                 {
00621                                                         temp_machine=*this;
00622                                                         temp_machine.add_write_transition(current, tape_symbol, *alpha_iter, first_unreachable_state);
00623                                                         output_machine(temp_machine, destination, alphabet);
00624                                                 }
00625                                                 else
00626                                                 {
00627                                                         temp_machine=*this;
00628                                                         temp_machine.add_write_transition(current, tape_symbol, *alpha_iter, first_unreachable_state);
00629                                                         g_counter_implicit.increment(tm_stats::simple_nonproductive, temp_machine.number_represented());
00630                                                         c_counter_implicit.increment(tm_stats::simple_nonproductive, 1);
00631                                                 }
00632                                         #else
00633                                                 temp_machine=*this;
00634                                                 temp_machine.add_write_transition(current, tape_symbol, *alpha_iter, first_unreachable_state);
00635                                                 output_machine(temp_machine, destination, alphabet);
00636                                         #endif
00637                                 }
00638                                 temp_machine=*this;
00639                                 temp_machine.add_move_transition(current, tape_symbol, left, first_unreachable_state);
00640                                 output_machine(temp_machine, destination, alphabet);
00641                                 temp_machine=*this;
00642                                 temp_machine.add_move_transition(current, tape_symbol, right, first_unreachable_state);
00643                                 output_machine(temp_machine, destination, alphabet);
00644                         }
00645 
00646                         //create transition to the halt state
00647                         temp_machine=*this;
00648                         temp_machine.add_write_transition(current, tape_symbol, tape_symbol, halt_state);
00649                         output_machine(temp_machine, destination, alphabet);
00650                 }
00651         }
00652 
00660         template <typename OutputIterator>
00661         void generate_tn_quadruple_children_explicit(const std::list<T> &alphabet, OutputIterator destination) const
00662         {
00663                 //store read symbol
00664                 T tape_symbol=tape.read();
00665 
00666                 //create a temp machine for use in generating children
00667                 turing_machine<T> temp_machine=*this;
00668 
00669                 //for each reachable (used) state:
00670                 for(transition_index_type end_state=0; end_state!=first_unreachable_state; ++end_state)
00671                 {
00672                         //for each possible write & move, create a child machine
00673                         for(typename std::list<T>::const_iterator alpha_iter=alphabet.begin(); alpha_iter!=alphabet.end(); ++alpha_iter)
00674                         {
00675                                 #ifdef no_ss_optimisation
00676                                         if((*alpha_iter)!=tape_symbol)
00677                                         {
00678                                                 temp_machine=*this;
00679                                                 temp_machine.add_write_transition(current, tape_symbol, *alpha_iter, end_state);
00680                                                 output_machine(temp_machine, destination, alphabet);
00681                                         }
00682                                 #else
00683                                         temp_machine=*this;
00684                                         temp_machine.add_write_transition(current, tape_symbol, *alpha_iter, end_state);
00685                                         output_machine(temp_machine, destination, alphabet);
00686                                 #endif
00687                         }
00688 
00689                         //for each move, create a child machine
00690                         temp_machine=*this;
00691                         temp_machine.add_move_transition(current, tape_symbol, left, end_state);
00692                         output_machine(temp_machine, destination, alphabet);
00693                         temp_machine=*this;
00694                         temp_machine.add_move_transition(current, tape_symbol, right, end_state);
00695                         output_machine(temp_machine, destination, alphabet);
00696                 }
00697 
00698                 //if this machine has a halt state (which, presumably, it should!)
00699                 if(halt_state_exists)
00700                 {
00701                         //if there is an unreachable state, create transitions to it
00702                         if(first_unreachable_state<halt_state)
00703                         {
00704                                 for(typename std::list<T>::const_iterator alpha_iter=alphabet.begin(); alpha_iter!=alphabet.end(); ++alpha_iter)
00705                                 {
00706                                         #ifdef no_ss_optimisation
00707                                                 if((*alpha_iter)!=tape_symbol)
00708                                                 {
00709                                                         temp_machine=*this;
00710                                                         temp_machine.add_write_transition(current, tape_symbol, *alpha_iter, first_unreachable_state);
00711                                                         output_machine(temp_machine, destination, alphabet);
00712                                                 }
00713                                         #else
00714                                                 temp_machine=*this;
00715                                                 temp_machine.add_write_transition(current, tape_symbol, *alpha_iter, first_unreachable_state);
00716                                                 output_machine(temp_machine, destination, alphabet);
00717                                         #endif
00718                                 }
00719                                 temp_machine=*this;
00720                                 temp_machine.add_move_transition(current, tape_symbol, left, first_unreachable_state);
00721                                 output_machine(temp_machine, destination, alphabet);
00722                                 temp_machine=*this;
00723                                 temp_machine.add_move_transition(current, tape_symbol, right, first_unreachable_state);
00724                                 output_machine(temp_machine, destination, alphabet);
00725                         }
00726 
00727                         //create transitions to the halt state
00728                         /*temp_machine=*this;
00729                         temp_machine.add_write_transition(current, tape_symbol, tape_symbol, halt_state);
00730                         output_machine(temp_machine, destination, alphabet);*/
00731                         for(typename std::list<T>::const_iterator alpha_iter=alphabet.begin() ; alpha_iter!=alphabet.end(); ++alpha_iter)
00732                         {
00733                                 #ifdef no_ss_optimisation
00734                                  if((*alpha_iter)!=tape_symbol)
00735                                         {
00736                                                 temp_machine=*this;
00737                                                 temp_machine.add_write_transition(current, tape_symbol, *alpha_iter, halt_state);
00738                                                 output_machine(temp_machine, destination, alphabet);
00739                                         }
00740                                 #else
00741                                         temp_machine=*this;
00742                                         temp_machine.add_write_transition(current, tape_symbol, *alpha_iter, halt_state);
00743                                         output_machine(temp_machine, destination, alphabet);
00744                                 #endif
00745                         }
00746                         temp_machine=*this;
00747                         temp_machine.add_move_transition(current, tape_symbol, left, halt_state);
00748                         output_machine(temp_machine, destination, alphabet);
00749                         temp_machine=*this;
00750                         temp_machine.add_move_transition(current, tape_symbol, right, halt_state);
00751                         output_machine(temp_machine, destination, alphabet);
00752                 }
00753         }
00754 
00762         template <typename OutputIterator>
00763         void generate_all_tn_quadruple_children(const std::list<T> &alphabet, OutputIterator destination) const
00764         {
00765                 //store read symbol
00766                 T tape_symbol=tape.read();
00767 
00768                 //create a temp machine for use in generating children
00769                 turing_machine<T> temp_machine=*this;
00770 
00771                 //for each reachable (used) state:
00772                 for(transition_index_type end_state=0; end_state!=first_unreachable_state; ++end_state)
00773                 {
00774                         //for each possible write & move, create a child machine
00775                         for(typename std::list<T>::const_iterator alpha_iter=alphabet.begin(); alpha_iter!=alphabet.end(); ++alpha_iter)
00776                         {
00777                                 #ifdef no_ss_optimisation
00778                                         if((*alpha_iter)!=tape_symbol)
00779                                         {
00780                                                 temp_machine=*this;
00781                                                 temp_machine.add_write_transition(current, tape_symbol, *alpha_iter, end_state);
00782                                                 output_machine(temp_machine, destination, alphabet);
00783                                         }
00784                                         else
00785                                         {
00786                                                 temp_machine=*this;
00787                                                 temp_machine.add_write_transition(current, tape_symbol, *alpha_iter, end_state);
00788                                                 g_counter_implicit.increment(tm_stats::simple_nonproductive, temp_machine.number_represented());
00789                                                 c_counter_implicit.increment(tm_stats::simple_nonproductive, 1);
00790                                                 g_counter_explicit.increment(tm_stats::simple_nonproductive, temp_machine.number_represented_explicit());
00791                                                 c_counter_explicit.increment(tm_stats::simple_nonproductive, 1);
00792                                         }
00793                                 #else
00794                                                 temp_machine=*this;
00795                                                 temp_machine.add_write_transition(current, tape_symbol, *alpha_iter, end_state);
00796                                                 output_machine(temp_machine, destination, alphabet);
00797                                 #endif
00798                         }
00799 
00800                         //for each move, create a child machine
00801                         temp_machine=*this;
00802                         temp_machine.add_move_transition(current, tape_symbol, left, end_state);
00803                         output_machine(temp_machine, destination, alphabet);
00804                         temp_machine=*this;
00805                         temp_machine.add_move_transition(current, tape_symbol, right, end_state);
00806                         output_machine(temp_machine, destination, alphabet);
00807                 }
00808 
00809                 //if this machine has a halt state (which, presumably, it should!)
00810                 if(halt_state_exists)
00811                 {
00812                         //if there is an unreachable state, create transitions to it
00813                         if(first_unreachable_state!=halt_state)
00814                         {
00815                                 for(typename std::list<T>::const_iterator alpha_iter=alphabet.begin(); alpha_iter!=alphabet.end(); ++alpha_iter)
00816                                 {
00817                                         #ifdef no_ss_optimisation
00818                                                 if((*alpha_iter)!=tape_symbol)
00819                                                 {
00820                                                         temp_machine=*this;
00821                                                         temp_machine.add_write_transition(current, tape_symbol, *alpha_iter, first_unreachable_state);
00822                                                         output_machine(temp_machine, destination, alphabet);
00823                                                 }
00824                                                 else
00825                                                 {
00826                                                         temp_machine=*this;
00827                                                         temp_machine.add_write_transition(current, tape_symbol, *alpha_iter, first_unreachable_state);
00828                                                         g_counter_implicit.increment(tm_stats::simple_nonproductive, temp_machine.number_represented());
00829                                                         c_counter_implicit.increment(tm_stats::simple_nonproductive, 1);
00830                                                         g_counter_explicit.increment(tm_stats::simple_nonproductive, temp_machine.number_represented_explicit());
00831                                                         c_counter_explicit.increment(tm_stats::simple_nonproductive, 1);
00832                                                 }
00833                                         #else
00834                                                 temp_machine=*this;
00835                                                 temp_machine.add_write_transition(current, tape_symbol, *alpha_iter, first_unreachable_state);
00836                                                 output_machine(temp_machine, destination, alphabet);
00837                                         #endif
00838                                 }
00839                                 temp_machine=*this;
00840                                 temp_machine.add_move_transition(current, tape_symbol, left, first_unreachable_state);
00841                                 output_machine(temp_machine, destination, alphabet);
00842                                 temp_machine=*this;
00843                                 temp_machine.add_move_transition(current, tape_symbol, right, first_unreachable_state);
00844                                 output_machine(temp_machine, destination, alphabet);
00845                         }
00846 
00847                         //create transition to the halt state
00848                         for(typename std::list<T>::const_iterator alpha_iter=alphabet.begin() ; alpha_iter!=alphabet.end(); ++alpha_iter)
00849                         {
00850                                 temp_machine=*this;
00851                                 temp_machine.add_write_transition(current, tape_symbol, *alpha_iter, halt_state);
00852                                 output_machine(temp_machine, destination, alphabet);
00853                         }
00854                         temp_machine=*this;
00855                         temp_machine.add_move_transition(current, tape_symbol, left, halt_state);
00856                         output_machine(temp_machine, destination, alphabet);
00857                         temp_machine=*this;
00858                         temp_machine.add_move_transition(current, tape_symbol, right, halt_state);
00859                         output_machine(temp_machine, destination, alphabet);
00860                 }
00861         }
00862 
00863         //begin Owen Kellett modifications
00869         bool resetMachine()
00870         {
00871                 //infinite_tape<T> newTape(tape.defaultValue());
00872                 tape.reset();
00873                 tape.reset_head();
00874                 current = 0;
00875                 steps = 0;
00876                 run_status = run;
00877                 return true;
00878         }
00879 
00885         turing_machine<T> reverseMachine()
00886         {
00887                 turing_machine<T> reverse(transition_function.size(), 0);
00888                 int j;
00889 
00890                 for(j = 0; j < transition_function.size(); j++)
00891                 {
00892                         T write;
00893                         typename infinite_tape<T>::direction move;
00894                         typename std::vector<state<T> >::size_type nextState;
00895 
00896                         if(transition_function[j].simulate_transition(0, write, move, nextState) == state<T>::run)
00897                         {
00898                                 switch(move)
00899                                 {
00900                                         case infinite_tape<T>::left:
00901                                                 reverse.add_move_transition(j,0, infinite_tape<T>::right, nextState);
00902                                                 break;
00903                                         case infinite_tape<T>::right:
00904                                                 reverse.add_move_transition(j,0, infinite_tape<T>::left, nextState);
00905                                                 break;
00906                                         case infinite_tape<T>::do_nothing:
00907                                                 reverse.add_write_transition(j,0, write, nextState);
00908                                 }
00909                         }
00910                         if(transition_function[j].simulate_transition(1, write, move, nextState) == state<T>::run)
00911                         {
00912                                 switch(move)
00913                                 {
00914                                         case infinite_tape<T>::left:
00915                                                 reverse.add_move_transition(j,1, infinite_tape<T>::right, nextState);
00916                                                 break;
00917                                         case infinite_tape<T>::right:
00918                                                 reverse.add_move_transition(j,1, infinite_tape<T>::left, nextState);
00919                                                 break;
00920                                         case infinite_tape<T>::do_nothing:
00921                                                 reverse.add_write_transition(j,1, write, nextState);
00922                                 }
00923                         }
00924                 }
00925                 return reverse;
00926         }
00927 
00940         void rigMachine(typename std::vector<T> &riggedTape,
00941                         int originalReadHead,
00942                         int desiredReadHead,
00943                         typename std::vector<state<T> >::size_type state,
00944                         typename std::list<T>::iterator &leftBound,
00945                         typename std::list<T>::iterator &rightBound,
00946                         typename std::list<T>::iterator &desiredLocation)
00947         {
00948                 resetMachine();
00949                 typename std::list<T>::iterator currentLocation = tape.currentLocation();
00950                 desiredLocation = tape.currentLocation();
00951                 leftBound = tape.currentLocation();
00952 
00953                 for(int j = 0; j < riggedTape.size(); j++)
00954                 {
00955                         if(j == originalReadHead)
00956                                 tape.setCurrentLocation(currentLocation);
00957                         *currentLocation = riggedTape[j];
00958                         tape.checkIteratorRight(currentLocation);
00959                         currentLocation++;
00960                 }
00961                 rightBound = currentLocation;
00962                 rightBound--;
00963                 if(desiredReadHead == -1)
00964                         desiredLocation--;
00965                 if(desiredReadHead == riggedTape.size())
00966                         desiredLocation = currentLocation;
00967 
00968                 current = state;
00969         }
00970 
00976         std::vector<state<T> >& stateSet()
00977         {
00978                 return transition_function;
00979         }
00980 
00986         transition_index_type haltState()
00987         {
00988                 if(!halt_state_exists)
00989                         return first_unreachable_state;
00990                 return halt_state;
00991         }
00992 
00998         move_type nextMove()
00999         {
01000                 T write;
01001                 move_type move;
01002                 typename std::vector<state<T> >::size_type nextState;
01003                 if(transition_function[current].simulate_transition(tape.read(), write, move, nextState) == state<T>::halt)
01004                         return halt_move;
01005                 return move;
01006         }
01007 
01014         void printTMO(std::ostream &out) const
01015         {
01016                 out << "digraph TM" << std::endl;
01017                 out << "{" << std::endl;
01018                 out << "/*This machine represents " << number_represented() << " machines*/" << std::endl;
01019                 out << "/*Settings*/" << std::endl;
01020                 out << "rankdir = LR;" << std::endl;
01021                 out << "start [shape=plaintext];" << std::endl;
01022                 out << "halt [shape=plaintext];" << std::endl;
01023 
01024                 typename std::vector<state<T> >::const_iterator i=transition_function.begin();
01025                 int count = 0;
01026                 T write;
01027                 typename infinite_tape<T>::direction move;
01028                 typename std::vector<state<T> >::size_type nextState;
01029                 for(count = 0; i!=transition_function.end(); ++i)
01030                 {
01031                         if(count != halt_state)
01032                                 out << (count++) << " [shape=circle];" << std::endl;
01033                 }
01034 
01035                 out << std::endl;
01036                 out << "/*GraphOutput*/" << std::endl;
01037                 out << "/*NumStates = " << count << "*/" << std::endl;
01038                 out << "/*Quadruple*/" << std::endl;
01039                 if(implicitMachine())
01040                         out << "/*Implicit*/" << std::endl;
01041                 else
01042                         out << "/*Explicit*/" << std::endl;
01043                 out << "start -> 0;" << std::endl;
01044 
01045                 i=transition_function.begin();
01046                 count = 0;
01047                 for(count = 0; i!=transition_function.end(); ++i, ++count)
01048                 {
01049                         if(count != halt_state)
01050                         {
01051                                 if((*i).simulate_transition(0, write, move, nextState) == state<T>::run)
01052                                 {
01053                                         if(nextState == halt_state && write == 0 && move == infinite_tape<T>::do_nothing)
01054                                                 out << count << " -> halt [label=\"" << 0 << "\"];" << std::endl;
01055                                         else
01056                                         {
01057                                                 if(nextState == halt_state)
01058                                                         out << count << " -> halt [label=\"" << 0 << ':';
01059                                                 else
01060                                                         out << count << " -> " << nextState << " [label=\"" << 0 << ':';
01061                                                 if(write != 0)
01062                                                         out << write << "\"];";
01063                                                 else
01064                                                 {
01065                                                         if(move == infinite_tape<T>::left)
01066                                                                 out << "L\"];";
01067                                                         else
01068                                                                 out << "R\"];";
01069                                                 }
01070                                                 out << std::endl;
01071                                         }
01072                                 }
01073                                 //else
01074                                         //out << count << " -> halt [label=\"" << 0 << "\"];" << std::endl;
01075                                 if((*i).simulate_transition(1, write, move, nextState) == state<T>::run)
01076                                 {
01077                                         if(nextState == halt_state && write == 1 && move == infinite_tape<T>::do_nothing)
01078                                                 out << count << " -> halt [label=\"" << 1 << "\"];" << std::endl;
01079                                         else
01080                                         {
01081                                                 if(nextState == halt_state)
01082                                                         out << count << " -> halt [label=\"" << 1 << ':';
01083                                                 else
01084                                                         out << count << " -> " << nextState << " [label=\"" << 1 << ':';
01085                                                 if(write != 1)
01086                                                         out << write << "\"];";
01087                                                 else
01088                                                 {
01089                                                         if(move == infinite_tape<T>::left)
01090                                                                 out << "L\"];";
01091                                                         else
01092                                                                 out << "R\"];";
01093                                                 }
01094                                                 out << std::endl;
01095                                         }
01096                                 }
01097                                 //else
01098                                         //out << count << " -> halt [label=\"" << 1 << "\"];" << std::endl;
01099                         }
01100                 }
01101                 out << "/*EndGraphOutput*/" << std::endl;
01102                 out << "}" << std::endl;
01103         }
01104 
01110         bool implicitMachine() const
01111         {
01112                 if(!halt_state_exists)
01113                         return true;
01114                 else
01115                 {
01116                         typename std::vector<state<T> >::const_iterator i=transition_function.begin();
01117                         T write;
01118                         typename infinite_tape<T>::direction move;
01119                         typename std::vector<state<T> >::size_type nextState;
01120                         for(i; i != transition_function.end(); i++)
01121                         {
01122                                 if((*i).simulate_transition(0, write, move, nextState) == state<T>::run)
01123                                 {
01124                                         if(nextState == halt_state && (write != 0 || move != infinite_tape<T>::do_nothing))
01125                                                 return false;
01126                                 }
01127                                 if((*i).simulate_transition(1, write, move, nextState) == state<T>::run)
01128                                 {
01129                                         if(nextState == halt_state && (write != 1 || move != infinite_tape<T>::do_nothing))
01130                                                 return false;
01131                                 }
01132                         }
01133                         return true;
01134                 }
01135         }
01136 
01137         //end Owen Kellett modifications
01138 
01139         private:
01140 
01141         template <typename OutputIterator>
01142         inline void output_machine(turing_machine<T>& to_output, OutputIterator destination) const
01143         {
01144                 std::cout<<"fuck"<<std::endl;
01145         }
01146 
01147         template <typename OutputIterator>
01148         inline void output_machine(turing_machine<T>& to_output, OutputIterator destination, const std::list<T> &alphabet) const
01149         {
01150                 #ifdef enable_optimisations
01151                         if(run_checks(to_output, alphabet))
01152                         {
01153                                 to_output.run_status=run;
01154                                 *(destination++)=to_output;
01155                         }
01156                 #else
01157                         to_output.run_status=run;
01158                         *(destination++)=to_output;
01159                 #endif
01160         }
01161 
01162         public:
01163         private:
01164 
01169         bool inline run_checks(const turing_machine<T> &to_check, const std::list<T> &alphabet) const
01170         {
01171                 #ifdef first_write_optimisation
01172                         T fw_write;
01173                         typename infinite_tape<T>::direction fw_move;
01174                         transition_index_type fw_next;
01175                         to_check.transition_function[0].simulate_transition(0, fw_write, fw_move, fw_next);
01176                         //if start state does not have 0:1 transition
01177                         if(fw_write!=1 || fw_move!=do_nothing)
01178                         {
01179                                 if(to_check.implicitMachine())
01180                                 {
01181                                         g_counter_implicit.increment(tm_stats::first_write_1, to_check.number_represented());
01182                                         c_counter_implicit.increment(tm_stats::first_write_1, 1);
01183                                 }
01184                                 g_counter_explicit.increment(tm_stats::first_write_1, to_check.number_represented_explicit());
01185                                 c_counter_explicit.increment(tm_stats::first_write_1, 1);
01186                                 return false;
01187                         }
01188 
01189                         #ifdef first_move_optimisation
01190                                 T fm_write;
01191                                 typename infinite_tape<T>::direction fm_move;
01192                                 transition_index_type fm_next;
01193                                 to_check.transition_function[fw_next].simulate_transition(1, fm_write, fm_move, fm_next);
01194                                 //if it's a move transition to the left ... if it's not a move, it must be an ss-transition or an ssprime-transition (i.e., 0:1 then 1:1=ss, 0:1 then 1:0=ssprime), so we don't handle that here
01195                                 if(fm_move==left)
01196                                 {
01197                                         if(to_check.implicitMachine())
01198                                         {
01199                                                 g_counter_implicit.increment(tm_stats::first_move_right, to_check.number_represented());
01200                                                 c_counter_implicit.increment(tm_stats::first_move_right, 1);
01201                                         }
01202                                         g_counter_explicit.increment(tm_stats::first_move_right, to_check.number_represented_explicit());
01203                                         c_counter_explicit.increment(tm_stats::first_move_right, 1);
01204                                         return false;
01205                                 }
01206                         #endif
01207                 #endif
01208 
01209                 #ifdef no_ssprime_sprimes_optimisation
01210                         //get information about current machine
01211                         T c_read=to_check.tape.read(), c_write;
01212                         typename infinite_tape<T>::direction c_move;
01213                         transition_index_type c_current=to_check.current, c_next;
01214 
01215                         //only need to check if we have a write-transition
01216                         if(to_check.transition_function[c_current].simulate_transition(c_read, c_write, c_move, c_next)==run && c_move==do_nothing)
01217                         {
01218                                 //check for the case where the currently-added transition forms the s:s' portion
01219                                 T n_read=c_write, n_write;
01220                                 typename infinite_tape<T>::direction n_move;
01221                                 transition_index_type n_current=c_next, n_next;
01222 
01223                                 //simulate transition and only continue check if a write-transition exists
01224                                 if(to_check.transition_function[n_current].simulate_transition(n_read, n_write, n_move, n_next)==run && n_move==do_nothing)
01225                                 {
01226                                         //read of first transition=write of second; write of first=read of second (trivially), so we have an c_read:c_write-c_write-c_read transition; eliminate
01227                                         if(c_read==n_write)
01228                                         {
01229                                                 if(to_check.implicitMachine())
01230                                                 {
01231                                                         g_counter_implicit.increment(tm_stats::complex_nonproductive, to_check.number_represented());
01232                                                         c_counter_implicit.increment(tm_stats::complex_nonproductive, 1);
01233                                                 }
01234                                                 g_counter_explicit.increment(tm_stats::complex_nonproductive, to_check.number_represented_explicit());
01235                                                 c_counter_explicit.increment(tm_stats::complex_nonproductive, 1);
01236                                                 return false;
01237                                         }
01238                                 }
01239 
01240                                 //check for the case where the currently-added transition forms the s':s portion
01241                                 T p_read=c_write, p_write;
01242                                 typename infinite_tape<T>::direction p_move;
01243                                 transition_index_type p_next;
01244 
01245                                 for(transition_index_type p_current=0, p_end=std::min(to_check.halt_state, to_check.first_unreachable_state); p_current!=p_end; ++p_current)
01246                                 {
01247                                         //remove a transition if -- given that the read is the current write -- it meets: 1)X exists 2)it is a quadruple write transition 3)the next state after the X transition is the current state 4)the symbol written is the same as the current read
01248                                         if(to_check.transition_function[p_current].simulate_transition(p_read, p_write, p_move, p_next)==run && p_move==do_nothing && p_next==c_current && p_write==c_read)
01249                                         {
01250                                                 if(to_check.implicitMachine())
01251                                                 {
01252                                                         g_counter_implicit.increment(tm_stats::complex_nonproductive, to_check.number_represented());
01253                                                         c_counter_implicit.increment(tm_stats::complex_nonproductive, 1);
01254                                                 }
01255                                                 g_counter_explicit.increment(tm_stats::complex_nonproductive, to_check.number_represented_explicit());
01256                                                 c_counter_explicit.increment(tm_stats::complex_nonproductive, 1);
01257                                                 return false;
01258                                         }
01259                                 }
01260                         }
01261                 #endif
01262 
01263                 return true;
01264         }
01265 
01266         public:
01267 
01268 protected:
01269         bool halt_state_exists;
01270         transition_index_type current, halt_state, first_unreachable_state;
01271         typename std::vector<state<T> > transition_function;
01272         infinite_tape<T> tape;
01273         transition_count_type steps;
01274         result_type run_status;
01275 };
01276 
01277 
01278 
01279 //displays a Turing machine
01280 //preconditions: to_print is a valid Turing machine
01281 //postconditions: to_print has been displayed according to the format specified by the print member function of the turing_machine class
01282 //complexity: equal to that of the print member function of the turing_machine class
01283 template <typename T>
01284 std::ostream& operator<<(std::ostream &out, const turing_machine<T> &to_print)
01285 {
01286         to_print.print(out);
01287         return out;
01288 }
01289 
01290 #endif

Generated on Thu Nov 20 00:17:32 2003 for BusyBeaver by doxygen 1.3.3