// This constructor creates a Turing machine definition. The arguments are: // (Note: We use "symbol" and "letter" as synonims.) // - the tape alphabet size (int, >= 1) // - a blank symbol (>= 0, <(alphabet size)) // - the set of letters that are part of the input alphabet, subset of the tape alphabet, // it is an array of bools of length = alphabet size. The blank symbol // must not be part of the input alphabet. newMachineInputAlphabet[a] contains // true of false whether or not letter a is part of the input alphabet. // - the number of states (int, >= 1) // - an initial state (>= 0, <(number of states)) // - a transition matrix, with lines being states, 3 columns beeing one letter and content being // the new state, the new letter and the direction. // ie. newMachinesTransitions[s1,3*a] = s2 means that when the machine is in state s1 // and reads letter a, it goes in state s2. Special values -1 and -2 respectively mean // reject and accept. // newMachinesTransitions[s1,3*a+1] = a2 means the written letter is a2 // newMachinesTransitions[s1,3*a+2] = d means the machine will go in direction d // with 0 beeing "don't move", 1 beeing "go one step right", and 2 beeing "go one step left". public TuringMachineDefinitionById(int newMachineTapeAlphabetSize, int newMachineBlankSymbol, FrozenVector <bool> newMachineInputAlphabet, int newMachineNumberOfStates, int newMachineInitialState, FrozenMatrix <int> newMachineTransitionMatrix) { /* Store tape alphabet size. */ if (!(newMachineTapeAlphabetSize >= 1)) { throw new TuringMachineException("Tape alphabet size should be >= 1, but it is " + newMachineTapeAlphabetSize); } tapeAlphabetSize = newMachineTapeAlphabetSize; /* Now check and store the blank symbol.. */ if (!(newMachineBlankSymbol >= 0 && newMachineBlankSymbol < tapeAlphabetSize)) { throw new TuringMachineException("Blank symbol (" + newMachineBlankSymbol + ") is out of range. It should be in [0," + tapeAlphabetSize + "["); } blank = newMachineBlankSymbol; /* Chack and store input alphabet. */ if (newMachineInputAlphabet != null) { if (newMachineInputAlphabet.Length != newMachineTapeAlphabetSize) { throw new TuringMachineException("Given input alphabet vector length (" + newMachineInputAlphabet.Length + ") should equal tape alphabet size (" + tapeAlphabetSize + ")."); } if (newMachineInputAlphabet[newMachineBlankSymbol]) { throw new TuringMachineException("Blank symbol must not be part of input alphabet."); } inputAlphabet = newMachineInputAlphabet; } else { // All but the blank symbol. var inputAlphabetTempMatrix = new bool[tapeAlphabetSize]; for (int i = 0; i < tapeAlphabetSize; i++) { if (i != newMachineBlankSymbol) { inputAlphabetTempMatrix[i] = true; } else { inputAlphabetTempMatrix[i] = false; } } inputAlphabet = new FrozenVector <bool>(inputAlphabetTempMatrix); } /* Store number of states. */ if (!(newMachineNumberOfStates >= 1)) { throw new TuringMachineException("Number of states should be >= 1, but it is " + tapeAlphabetSize); } numberOfStates = newMachineNumberOfStates; /* Now check and store the initial state. */ if (!(newMachineInitialState >= 0 && newMachineInitialState < numberOfStates)) { throw new TuringMachineException("Initial state (" + newMachineInitialState + ") is out of range. It should be in [0," + numberOfStates + "["); } initialState = newMachineInitialState; /* Now check the transition matrix and store optimized version * of this matrix using ints for destination states. */ if (newMachineTransitionMatrix.GetLength(0) != numberOfStates) { throw new TuringMachineException("Transition matrix has " + newMachineTransitionMatrix.GetLength(0) + " lines while it should have " + numberOfStates + " lines which is the number of states."); } if (newMachineTransitionMatrix.GetLength(1) != 3 * tapeAlphabetSize) { throw new TuringMachineException("Transition matrix has " + newMachineTransitionMatrix.GetLength(1) + " columns while it should have " + (3 * tapeAlphabetSize) + " columns which is 3 times the number of letters in the alphabet."); } for (int s = 0; s < numberOfStates; s++) { for (int l = 0; l < tapeAlphabetSize; l += 3) { if (!(newMachineTransitionMatrix[s, l] >= -2 && newMachineTransitionMatrix[s, l] < numberOfStates)) { throw new TuringMachineException("Transitions matrix references a state (" + newMachineTransitionMatrix[s, l] + ") that is out of range. It should be in [-2," + numberOfStates + "["); } if (!(newMachineTransitionMatrix[s, l + 1] >= 0 && newMachineTransitionMatrix[s, l + 1] < tapeAlphabetSize)) { throw new TuringMachineException("Transitions matrix references a letter (" + newMachineTransitionMatrix[s, l] + ") that is out of range. It should be in [0," + tapeAlphabetSize + "["); } if (!(newMachineTransitionMatrix[s, l + 2] >= -1 && newMachineTransitionMatrix[s, l + 2] <= 1)) { throw new TuringMachineException("Transitions matrix references a direction (" + newMachineTransitionMatrix[s, l] + ") that is out of range. It should be in [-1,1]."); } } } transitionMatrix = newMachineTransitionMatrix; }
// This constructor creates a Turing machine definition. The arguments are: // (Note: We use "symbol" and "letter" as synonims.) // // IDS OR CUSTOM TYPES? // States and letters have a double representation. They can bee seen as // integer ids (positions in the matrix, newMachineBlankSymbolId, newMachineInitialStateId) // or as TState and TAlphabet (types you choose). The mapping between this 2 representations // is acomplished using newMachineTapeAlphabet and newMachineStates. It is not mandatory // to use this 2 representations. You may be happy with just integers. In that case, // pass <int,int> as <TAlphabet,TState> and null as newMachineTapeAlphabet and newMachineStates. // The number of states and letters will then be computer using matrix lengths. // You can have a mix of the 2, for example state as ids only but letters as cutom type. // // - the tape alphabet (length >= 1) // - a blank symbol (>= 0, <(alphabet size)) // - the set of letters that are part of the input alphabet, subset of the tape alphabet, // it is an array of bools of length = alphabet size. The blank symbol // must not be part of the input alphabet. newMachineInputAlphabet[a] contains // true of false whether or not letter a is part of the input alphabet. // If you want the input alphabet to be all the tape alphabet except blank, // then you can pass null as this argument. // - states (length >= 1) // - an initial state (>= 0, <(number of states)) // - a transition matrix, with lines being states, 3 columns beeing one letter and content being // the new state, the new letter and the direction. // ie. newMachinesTransitions[s1,3*a] = s2 means that when the machine is in state s1 // and reads letter a, it goes in state s2. Special values -1 and -2 respectively mean // reject and accept. // newMachinesTransitions[s1,3*a+1] = a2 means the written letter is a2 // newMachinesTransitions[s1,3*a+2] = d means the machine will go in direction d // with 0 beeing "don't move", 1 beeing "go one step right", and 2 beeing "go one step left". // // About FrozenVector and FrozenMatrix: // This object requires that you use FrozenVector and FrozenMatrix for // the transitions matrix and the vector of final states. // As FrozenVector and FrozenMatrix are read-only, they can safely be // shared accross machines definitions. For convenience, a overrided // constructor is provided, that takes usual arrays, and converts them // to FrozenMatrix/Vector. // public TuringMachineDefinition(ICollection <TAlphabet> newMachineTapeAlphabet, int newMachineBlankSymbolId, FrozenVector <bool> newMachineInputAlphabet, ICollection <TState> newMachineStates, int newMachineInitialStateId, FrozenMatrix <int> newMachineTransitions) { int tapeAlphabetSize; /* Store alphabet and check it is correct (ie no duplicates). */ if (newMachineTapeAlphabet != null) { tapeAlphabet = new TAlphabet[newMachineTapeAlphabet.Count]; newMachineTapeAlphabet.CopyTo(tapeAlphabet, 0); tapeAlphabetIds = new Dictionary <TAlphabet, int>(); int i = 0; foreach (TAlphabet a in newMachineTapeAlphabet) { if (tapeAlphabetIds.ContainsKey(a)) { throw new FiniteStateMachineException("Duplicated letter in newMachineAlphabet : " + a); } tapeAlphabetIds.Add(a, i); i++; } // newMachineAlphabet array has authority for giving the number of letters tapeAlphabetSize = tapeAlphabet.Length; } else { if (typeof(TAlphabet) != typeof(int)) { throw new FiniteStateMachineException("You passed null as newMachineAlphabet, so I deduce that you want to identify" + " letters with ids instead of TAlphabet type, but did not choose int as TAlphabet" + " so this is inconsistant."); } // the matrix has authority for giving the number of letters tapeAlphabetSize = newMachineTransitions.GetLength(1) / 3; } int numberOfStates; /* Store states and check it is correct (ie no duplicates). */ if (newMachineStates != null) { states = new TState[newMachineStates.Count]; newMachineStates.CopyTo(states, 0); stateIds = new Dictionary <TState, int>(); int i = 0; foreach (TState s in newMachineStates) { if (stateIds.ContainsKey(s)) { throw new FiniteStateMachineException("Duplicated state in newMachineStates : " + s); } stateIds.Add(s, i); i++; } // newMachineStates array has auothority for giving the number of letters numberOfStates = states.Length; } else { if (typeof(TState) != typeof(int)) { throw new FiniteStateMachineException("You passed null as newMachineStates, so I deduce that you want to identify" + " states with ids instead of TState type, but did not choose int as TState" + " so this is inconsistant."); } // the matrix has authority for giving the number of states numberOfStates = newMachineTransitions.GetLength(0); } /* Now build our internal FiniteStateMachineDefinitionById. */ definitionById = new TuringMachineDefinitionById(tapeAlphabetSize, newMachineBlankSymbolId, newMachineInputAlphabet, numberOfStates, newMachineInitialStateId, newMachineTransitions); }
/* This constructor creates a finite state machine definition. The arguments are: * - the alphabet size (int, >= 0) * - the number of states (int, >= 1) * - an initial state (>= 0, <(number of states)) * - a transition matrix, with lines being states, columns beeing letters and content being the new states, * ie newMachinesTransitions[s1,a] = s2 means that when the machine is in state s1 * and reads letter a, it goes in state s2. * - an array of booleans, as many as states, which say if the state is final or not */ public FiniteStateMachineDefinitionById(int newMachineAlphabetSize, int newMachineNumberOfStates, int newMachineInitialState, FrozenMatrix <int> newMachineTransitionMatrix, FrozenVector <bool> newMachineFinalStates) { /* Store alphabet size. */ if (!(newMachineAlphabetSize >= 0)) { throw new FiniteStateMachineException("Alphabet size is negative (" + newMachineAlphabetSize + ")"); } alphabetSize = newMachineAlphabetSize; /* Store number of states. */ if (!(newMachineNumberOfStates >= 1)) { throw new FiniteStateMachineException("Number of states should be >= 1, but it is " + newMachineAlphabetSize); } numberOfStates = newMachineNumberOfStates; /* Now check and store the initial state. */ if (!(newMachineInitialState >= 0 && newMachineInitialState < numberOfStates)) { throw new FiniteStateMachineException("Initial state (" + newMachineInitialState + ") is out of range. It should be in [0," + numberOfStates + "["); } initialState = newMachineInitialState; /* Now check the transition matrix and store optimized version * of this matrix using ints for destination states. */ if (newMachineTransitionMatrix.GetLength(0) != numberOfStates) { throw new FiniteStateMachineException("Transition matrix has " + newMachineTransitionMatrix.GetLength(0) + " lines while it should have " + numberOfStates + " lines which is the number of states."); } if (newMachineTransitionMatrix.GetLength(1) != alphabetSize) { throw new FiniteStateMachineException("Transition matrix has " + newMachineTransitionMatrix.GetLength(1) + " columns while it should have " + alphabetSize + " columns which is the number of letters in the alphabet."); } for (int s = 0; s < numberOfStates; s++) { for (int l = 0; l < alphabetSize; l++) { if (!(newMachineTransitionMatrix[s, l] >= 0 && newMachineTransitionMatrix[s, l] < numberOfStates)) { throw new FiniteStateMachineException("Transitions matrix references a state (" + newMachineTransitionMatrix[s, l] + ") that is out of range. It should be in [0," + numberOfStates + "["); } } } transitionMatrix = newMachineTransitionMatrix; /* Check and store final states. */ if (newMachineFinalStates.Length != numberOfStates) { throw new FiniteStateMachineException("Final states array has " + newMachineFinalStates.Length + " elements while it should have " + numberOfStates + " elements which is the number of states."); } finalStates = newMachineFinalStates; }