Click here to Skip to main content
15,888,803 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.IO;
using System.Text;
using System.Threading;

namespace FSA
{
	/// <summary>
	/// Extends standard FSA functionality by adding event notifications.
	/// </summary>
	public class EventedAutomaton : FiniteStateAutomaton
	{
		private readonly FiniteStateAutomaton fsa;
		private int lastOutput;
		private int outputTime;	// how long the same output was produced
		private int stateTime; // how long the machine remained in the same state
		private readonly List<int> outputInput = new List<int>(); // What input sent to the machine since last output change
		private readonly List<int> outputStates = new List<int>(); // What is the state transition history since last output change
		private readonly List<int> stateInput = new List<int>(); // What input sent to the machine since last state change
		private readonly List<int> stateOutput = new List<int>(); // What output was produced since last state change
		//private readonly List<int> prevOutputInput = new List<int>(); // What input sent to the machine since last output change
		//private readonly List<int> prevOutputStates = new List<int>(); // What is the state transition history since last output change
		//private readonly List<int> prevStateInput = new List<int>(); // What input sent to the machine since last state change
		//private readonly List<int> prevStateOutput = new List<int>(); // What output was produced since last state change

		public event EventHandler<FsaEventArgs> StateChanged;
		public event EventHandler<FsaEventArgs> OutputChange;
		public event EventHandler<FsaEventArgs> Moved;

		public EventedAutomaton(FiniteStateAutomaton fsa)
		{
			this.fsa = fsa;
		}

		public IEnumerable<int> OutputInput
		{
			get { return outputInput; }
		}

		public IEnumerable<int> OutputStates
		{
			get { return outputStates; }
		}

		public IEnumerable<int> StateOutput
		{
			get { return stateOutput; }
		}

		public IEnumerable<int> StateInput
		{
			get { return stateInput; }
		}

		public FiniteStateAutomaton Fsa
		{
			get { return fsa; }
		}

		private void InvokeMoved(FsaEventArgs e)
		{
			EventHandler<FsaEventArgs> movedHandler = Moved;
			if (movedHandler != null) movedHandler(this, e);
		}

		private void InvokeStateChanged(FsaEventArgs e)
		{
			EventHandler<FsaEventArgs> stateLeavedHandler = StateChanged;
			if (stateLeavedHandler != null) stateLeavedHandler(this, e);
		}
		private void InvokeOutputChange(FsaEventArgs e)
		{
			EventHandler<FsaEventArgs> outputChangeHandler = OutputChange;
			if (outputChangeHandler != null) outputChangeHandler(this, e);
		}



		public override void Reset()
		{
			lastOutput = 0;
			outputTime = stateTime = 0;
			outputStates.Clear();
			outputInput.Clear();
			stateOutput.Clear();
			stateInput.Clear();
			Fsa.Reset();
		}
		public override int Send(int input)
		{
			int prevState = Fsa.CurrentState;

			int output = Fsa.Send(input);
			FsaEventArgs e;
			e = new FsaEventArgs {
				CurrentState = Fsa.CurrentState,
				Output = output,
				What = FsaEvents.OutputChanged,
				PreviousOutput = lastOutput,
				State = prevState,
				Automaton = this
			};
			if (output != lastOutput) {
				InvokeOutputChange(e);
				outputTime = 0;
				outputStates.Clear();
				outputInput.Clear();
			}
			lastOutput = output;
			outputTime++;
			outputStates.Add(Fsa.CurrentState);
			outputInput.Add(input);
			if (prevState != Fsa.CurrentState) {
				InvokeStateChanged(e);
				stateOutput.Clear();
				stateInput.Clear();
				stateTime = 0;
			}
			stateTime++;
			stateOutput.Add(output);
			stateInput.Add(input);
			InvokeMoved(e);
			return output;
		}
		public override FiniteStateAutomaton ShallowCopy()
		{
			EventedAutomaton clone = new EventedAutomaton(Fsa.ShallowCopy());
			clone.Moved = Moved;
			clone.OutputChange = OutputChange;
			clone.StateChanged = StateChanged;
			return clone;
		}
	}
}

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