|
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.
My name is Jacek. Currently, I am a Java/kotlin developer. I like C# and Monthy Python's sense of humour.