Click here to Skip to main content
15,892,059 members
Articles / Programming Languages / C#

An Object-oriented Approach to Finite State Automata

Rate me:
Please Sign up or sign in to vote.
4.85/5 (19 votes)
3 Feb 2009CPOL7 min read 61.8K   1.1K   55  
A brief introduction to FSA and a ready-to-use class library
using System;
using System.Collections.Generic;
using System.Text;

namespace FSA
{
	public class MealyAutomaton : FiniteStateAutomaton
	{
		private readonly MealyState[] states = new MealyState[0];

		public MealyAutomaton(MealyState[] states)
		{
			if (states == null)
					throw new ArgumentNullException("states");
			this.states = states;
		}

		public override void Reset()
		{
			CurrentState = 0;
		}
		public override int Send(int input)
		{
			MealySymbol symbol = states[CurrentState].Table[input];
			CurrentState = symbol.State;
			return states[CurrentState].Table[input].Output;
		}
		public override FiniteStateAutomaton ShallowCopy()
		{
			return new MealyAutomaton(states);
		}

		// With bounds checking
		public int SendSafe(int input)
		{
			if (input < 0 || input >= states[CurrentState].Table.Length)
				throw new ArgumentOutOfRangeException("input");
			MealySymbol symbol = states[CurrentState].Table[input];
			if (symbol.State < 0 || symbol.State >= states.Length)
				throw new InvalidOperationException(string.Format("Cannot move to state {0} (index out of bounds).", symbol.State));
			else
				CurrentState = symbol.State;
			return states[CurrentState].Table[input].Output;
		}
		public MooreAutomaton ToMoore()
		{
			throw new NotImplementedException("Why would somebody want such a conversion?");
		}
		/// <summary>Makes a quick-and-dirty run of a Moore machine given in a table form. This method does
		/// not check if the tables are valid. Creating them by hand is not recommended; use the GetTables method.</summary>
		/// <param name="mooreTables">The Moore automaton tables. See the <see cref="MooreTables"/> structure.</param>
		/// <param name="Z">Input data. Z[i] = the i-th call to Send method (virtually, because the Send method is not actually used).</param>
		/// <returns>An array of output data.</returns>
		public unsafe static int[] FastRun(MealyTables mooreTables, int[] Z)
		{
			if (mooreTables.Q == null)
				throw new ArgumentException("One of the tables is null. Possibly the automaton does not have any state.", "mooreTables");
			int Z_len = Z.Length;
			int[,,] Q = mooreTables.Q;
			int stateLen = 2 * Q.GetLength(1);
			int[] Y = new int[Z_len];
			fixed (int* _q = Q) {
				int* q = _q;
				int y_i = 0;
					fixed (int* _z = Z) {
						for (int* z = _z; *q >= 0 && z - _z < Z_len; z++, y_i++) {
							int* nextq = q + 2* *z;
							Y[y_i] = *(nextq + 1);
							q = _q + stateLen * *nextq;
						}
					}
			}
			return Y;
		}
		/// <summary>Does a fast Moore automaton execution and returns the output as a int[] table.</summary>
		/// <remarks>This method calls GetTables method sends the return value to the FastRun(DirtyMoore dirtyMoore, int[] Z) method.</remarks>
		/// <param name="input">Table of input symbol. Virtually, Z[i] = the i-th call to Send method.</param>
		/// <returns>An array of output data.</returns>
		public int[] FastRun(int[] input)
		{
			return FastRun(GetTables(), input);
		}
		/// <summary>Generates the tables of this Moore automaton.</summary>
		public MealyTables GetTables()
		{
			int stateCount = states.Length;
			if (stateCount == 0)
				return new MealyTables();
			int stateLen = GetStateLength();

			int[,,] Q = new int[stateCount, stateLen,2];
			for (int i = 0; i < stateCount; i++)
				if (states[i] != null)
					for (int j = 0; j < stateLen; j++) {
						Q[i, j, 0] = states[i].Table[j].State;
						Q[i, j, 1] = states[i].Table[j].Output;
					}

			return new MealyTables {
				Q = Q,
			};
		}
		private int GetStateLength()
		{
			int stateCount = states.Length;
			int stateLen = states[0].Table.Length;
			for (int i = 0; i < stateCount; i++)
				if (states[i] != null && states[i].Table.Length != stateLen)
					throw new FsaException("All states must have table of the same size to perform this operation.");
			return stateLen;
		}
	}
	/// <summary>Moore Automaton in Q and R tables form.</summary>
	public struct MealyTables
	{
		/// <summary>Table of states in form Q[i][j][0] = what is the next state if j was sent while being in i-th state;
		///  Q[i][j][1] = the output which will be produced.</summary>
		public int[,,] Q;
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
Poland Poland
My name is Jacek. Currently, I am a Java/kotlin developer. I like C# and Monthy Python's sense of humour.

Comments and Discussions