/// <summary>
        /// Gets the state machine for a timestamp corresponding to a Motorola SMS.
        /// </summary>
        /// <param name="weight">Weight of TimeStamp_MotoSms state machine, among the set of state machines to be aggregated, governing a prior probability that the inferred sequence of states corresponds to TimeStamp_MotoSms state machine.</param>
        /// <returns></returns>
        public static StateMachine GetTimestamp_MotoSms(int weight)
        {
            var timestamp = new StateMachine { Name = MachineList.TimeStamp_MotoSms, _weight = weight };

            State year = new State { Name = "Year", ParentStateMachine = timestamp };
            State month = new State { Name = "Month", ParentStateMachine = timestamp };
            State day = new State { Name = "Day", ParentStateMachine = timestamp };
            State hour = new State { Name = "Hour", ParentStateMachine = timestamp };
            State minute = new State { Name = "Minute", ParentStateMachine = timestamp };
            MotoSmsTimeState second = new MotoSmsTimeState { Name = "Second", ParentStateMachine = timestamp };

            timestamp.AddState(year);
            timestamp.AddState(month);
            timestamp.AddState(day);
            timestamp.AddState(hour);
            timestamp.AddState(minute);
            timestamp.AddState(second);

            timestamp.StartingStates.Add(year);
            timestamp.EndingStates.Add(second);

            AddTransition(year, month, 1f);
            AddTransition(month, day, 1f);
            AddTransition(day, hour, 1f);
            AddTransition(hour, minute, 1f);
            AddTransition(minute, second, 1f);

            // Year from 1970

            int yearWeight = 0;
            //int startYr = Math.Max(2010, TimeConstants.START_YEAR);
            int startYr = TimeConstants.START_YEAR;
            for (int i = (startYr - 1970); i <= (TimeConstants.END_YEAR - 1970); i++)
            {
                year.PossibleValueProbabilities[i] = 1f + yearWeight;

                yearWeight++;
            }

            for (byte i = 0x01; i <= 0x0c; i++)
            {
                month.PossibleValueProbabilities[i] = 1f;
            }

            for (byte i = 0x01; i <= 0x1f; i++)
            {
                day.PossibleValueProbabilities[i] = 1f;
            }

            for (byte i = 0x00; i <= 0x17; i++)
            {
                hour.PossibleValueProbabilities[i] = 1f;
            }

            for (byte i = 0x00; i <= 0x39; i++)
            {
                minute.PossibleValueProbabilities[i] = 1f;
                second.PossibleValueProbabilities[i] = 1f;
            }

            year.NormalizeProbabilities();
            month.NormalizeProbabilities();
            day.NormalizeProbabilities();
            hour.NormalizeProbabilities();
            minute.NormalizeProbabilities();
            second.NormalizeProbabilities();

            return timestamp;
        }
        public static StateMachine GetSqliteRecord(int weight)
        {
            var sqlite = new StateMachine { Name = MachineList.Sql_SqliteRecord, _weight = weight };
            var length = new State { Name = "HeaderLength", ParentStateMachine = sqlite };
            var varintLastByte = new SqliteHeaderLengthState()
                                     {
                                         Name = "VarintLast",
                                         ParentStateMachine = sqlite,
                                         LengthState = length,
                                         AllValuesPossible = true
                                     };
            var recordByte = new State() { Name = "SqlRecord", ParentStateMachine = sqlite, AllValuesPossible = true };
            var recordByteEnd = new SqliteRecordLengthState()
                                    {
                                        Name = "SqlRecordEnd",
                                        ParentStateMachine = sqlite,
                                        LengthState = length,
                                        AllValuesPossible = true,
                                        IsSplitState = true
                                    };

            sqlite.AddState(length);
            sqlite.AddState(varintLastByte);
            sqlite.AddState(recordByte);
            sqlite.AddState(recordByteEnd);

            sqlite.StartingStates.Add(length);
            sqlite.EndingStates.Add(recordByteEnd);

            AddTransition(length, varintLastByte, 0.9f);
            AddTransition(varintLastByte, varintLastByte, 0.2f);
            AddTransition(varintLastByte, recordByte, 0.8f);
            //will only accept sqlite records with at least one column byte
            AddTransition(recordByte, recordByte, 0.5f);
            AddTransition(recordByte, recordByteEnd, 0.5f);

            var stateWeight = 128f;

            //Let's only consider sql records with at least 1 column,
            //but no more than 127. This way the header length varint
            //will only be a single byte
            for (byte i = 0x02; i <= 0x7f; i++)
            {
                length.PossibleValueProbabilities[i] = stateWeight;
                stateWeight--;
            }

            length.NormalizeProbabilities();

            return sqlite;
        }
        /// <summary>
        /// Two unsigned 4-byte little-endian epoch times.
        /// </summary>
        /// <param name="weight">Weight of TimeStamp_Epoch1900Tuple state machine, among the set of state machines to be aggregated, governing a prior probability that the inferred sequence of states corresponds to TimeStamp_Epoch1900Tuple state machine.</param>
        /// <returns></returns>        
        public static StateMachine GetTimestamp_Epoch1900Tuple(int weight)
        {
            var timestamp = new StateMachine { Name = MachineList.TimeStamp_Epoch1900Tuple, _weight = weight };

            State epochTime1 = new State { Name = "Epoch1900Tuple1", ParentStateMachine = timestamp };
            State epochTime2 = new State { Name = "Epoch1900Tuple2", ParentStateMachine = timestamp };
            State epochTime3 = new State { Name = "Epoch1900Tuple3", ParentStateMachine = timestamp };
            State epochTime4 = new State { Name = "Epoch1900Tuple4", ParentStateMachine = timestamp };
            State epochTime5 = new State { Name = "Epoch1900Tuple5", ParentStateMachine = timestamp };
            State epochTime6 = new State { Name = "Epoch1900Tuple6", ParentStateMachine = timestamp };
            State epochTime7 = new State { Name = "Epoch1900Tuple7", ParentStateMachine = timestamp };
            Epoch1900Tuple epochTime8 = new Epoch1900Tuple { Name = "Epoch1900Tuple8", ParentStateMachine = timestamp };
            //State epochTime8 = new State { Name = "Epoch1900Tuple8", ParentStateMachine = timestamp };

            timestamp.AddState(epochTime1);
            timestamp.AddState(epochTime2);
            timestamp.AddState(epochTime3);
            timestamp.AddState(epochTime4);
            timestamp.AddState(epochTime5);
            timestamp.AddState(epochTime6);
            timestamp.AddState(epochTime7);
            timestamp.AddState(epochTime8);

            timestamp.StartingStates.Add(epochTime1);
            timestamp.EndingStates.Add(epochTime8);

            AddTransition(epochTime1, epochTime2, 1d);
            AddTransition(epochTime2, epochTime3, 1d);
            AddTransition(epochTime3, epochTime4, 1d);
            AddTransition(epochTime4, epochTime5, 1d);
            AddTransition(epochTime5, epochTime6, 1d);
            AddTransition(epochTime6, epochTime7, 1d);
            AddTransition(epochTime7, epochTime8, 1d);

            DateTime epochTime = new DateTime(1900, 1, 1, 0, 0, 0, DateTimeKind.Utc);
            //DateTime startTime = new DateTime(Math.Max(TimeConstants.START_YEAR, 2011), 1, 1, 0, 0, 0, DateTimeKind.Utc);
            DateTime startTime = new DateTime(TimeConstants.START_YEAR, 1, 1, 0, 0, 0, DateTimeKind.Utc);
            DateTime endTime = new DateTime(TimeConstants.END_YEAR, 12, 31, 23, 59, 59, DateTimeKind.Utc);
            uint startEpoch = (uint)(startTime - epochTime).TotalSeconds;
            uint endEpoch = (uint)(endTime - epochTime).TotalSeconds;
            byte[] startEpochBytes = BitConverter.GetBytes(startEpoch);
            byte[] endEpochBytes = BitConverter.GetBytes(endEpoch);
            // little-endian
            for (byte i = startEpochBytes[3]; i <= endEpochBytes[3]; i++)
            {
                epochTime4.PossibleValueProbabilities[i] = 1d;
                epochTime8.PossibleValueProbabilities[i] = 1d;
            }
            epochTime4.NormalizeProbabilities();
            epochTime8.NormalizeProbabilities();

            if (startEpochBytes[3] == endEpochBytes[3])
            {
                for (byte i = startEpochBytes[2]; i <= endEpochBytes[2]; i++)
                {
                    epochTime3.PossibleValueProbabilities[i] = 1d;
                    epochTime7.PossibleValueProbabilities[i] = 1d;
                }
                epochTime3.NormalizeProbabilities();
                epochTime7.NormalizeProbabilities();
            }
            else
            {
                for (int i = 0; i < 256; i++)
                {
                    epochTime3.PossibleValueProbabilities[i] = 1 / 256d;
                    epochTime7.PossibleValueProbabilities[i] = 1 / 256d;
                }
            }

            for (int i = 0; i < 256; i++)
            {
                epochTime1.PossibleValueProbabilities[i] = 1 / 256d;
                epochTime2.PossibleValueProbabilities[i] = 1 / 256d;
                epochTime5.PossibleValueProbabilities[i] = 1 / 256d;
                epochTime6.PossibleValueProbabilities[i] = 1 / 256d;
            }

            return timestamp;
        }
 /// <summary>
 /// Defines the value probabilities for a user defined byte.
 /// </summary>
 /// <param name="state">State machine.</param>
 /// <param name="userByte">UserByte object representing the byte.</param>
 public static void UserDefinedByteProbabilities(State state, UserByte userByte)
 {
     if (userByte.All)
     {
         state.IsBinary = true;
     }
     else
     {
         foreach (byte b in userByte.Values)
         {
             state.PossibleValueProbabilities[b] = 1d;
         }
         state.NormalizeProbabilities();
     }
 }
        /// <summary>
        /// Gets the meta state machine for a generic Call Log.
        /// </summary>
        /// <param name="weight">Weight of CallLogGeneric4 state machine, among the set of state machines to be aggregated, governing a prior probability that the inferred sequence of states corresponds to CallLogGeneric4 state machine.</param>
        /// <returns></returns>
        public static StateMachine GetMeta_CallLogGeneric4(int weight)
        {
            StateMachine metaCallLog = new StateMachine { Name = MachineList.Meta_CallLogGeneric4, _weight = weight };

            State text = new State { Name = "Text", ParentStateMachine = metaCallLog };
            State binaryA = new State { Name = "Binary", ParentStateMachine = metaCallLog, IsBinary = true };
            State binaryB = new State { Name = "Binary", ParentStateMachine = metaCallLog, IsBinary = true };
            State binaryX = new State { Name = "Binary", ParentStateMachine = metaCallLog, IsBinary = true };
            State phoneNumberA = new State { Name = "PhoneNumber", ParentStateMachine = metaCallLog };
            State timeStampA = new State { Name = "TimeStamp", ParentStateMachine = metaCallLog };

            metaCallLog.AddState(text);
            metaCallLog.AddState(binaryA);
            metaCallLog.AddState(binaryB);
            metaCallLog.AddState(binaryX);
            metaCallLog.AddState(phoneNumberA);
            metaCallLog.AddState(timeStampA);

            metaCallLog.StartingStates.Add(timeStampA);
            metaCallLog.EndingStates.Add(text);

            //Starting path timestamp -> number -> txt
            AddTransition(timeStampA, binaryA, 1f);
            AddTransition(binaryA, phoneNumberA, 1f);
            //AddTransition(binaryA, binaryA, 0.01f);
            AddTransition(phoneNumberA, binaryB, 1f);
            AddTransition(binaryB, text, 1f);
            //AddTransition(phoneNumberA, text, 1f);
            //AddTransition(binaryB, binaryB, 0.01f);
            AddTransition(text, binaryX, 1f);

            for (int i = 0; i < 256; i++)
            {
                binaryA.PossibleValueProbabilities[i] = 1f;
                binaryB.PossibleValueProbabilities[i] = 1f;
                binaryX.PossibleValueProbabilities[i] = 1f;
            }

            binaryA.PossibleValueProbabilities[(byte)MetaMachine.PhoneNumber] = 0f;
            binaryA.PossibleValueProbabilities[(byte)MetaMachine.Text] = 0f;
            binaryA.PossibleValueProbabilities[(byte)MetaMachine.TimeStamp] = 0f;
            binaryA.PossibleValueProbabilities[(byte)MetaMachine.BinaryLarge] = 0f;

            binaryB.PossibleValueProbabilities[(byte)MetaMachine.PhoneNumber] = 0f;
            binaryB.PossibleValueProbabilities[(byte)MetaMachine.Text] = 0f;
            binaryB.PossibleValueProbabilities[(byte)MetaMachine.TimeStamp] = 0f;
            binaryB.PossibleValueProbabilities[(byte)MetaMachine.BinaryLarge] = 0f;

            binaryX.PossibleValueProbabilities[(byte)MetaMachine.PhoneNumber] = 0f;
            binaryX.PossibleValueProbabilities[(byte)MetaMachine.Text] = 0f;
            binaryX.PossibleValueProbabilities[(byte)MetaMachine.TimeStamp] = 0f;
            binaryX.PossibleValueProbabilities[(byte)MetaMachine.BinaryLarge] = 0f;

            binaryA.NormalizeProbabilities();
            binaryB.NormalizeProbabilities();
            binaryX.NormalizeProbabilities();

            text.PossibleValueProbabilities[(byte)MetaMachine.Text] = 1f;
            phoneNumberA.PossibleValueProbabilities[(byte)MetaMachine.PhoneNumber] = 1f;
            timeStampA.PossibleValueProbabilities[(byte)MetaMachine.TimeStamp] = 1f;

            return metaCallLog;
        }
        /// <summary>
        /// Gets the state machine for a timestamp correponding to an SMS.
        /// </summary>
        /// <param name="weight">Weight of TimeStamp_Sms state machine, among the set of state machines to be aggregated, governing a prior probability that the inferred sequence of states corresponds to TimeStamp_Sms state machine.</param>
        /// <returns></returns>
        public static StateMachine GetTimestamp_Sms(int weight)
        {
            var timestamp = new StateMachine { Name = MachineList.TimeStamp_Sms, _weight = weight };

            State year = new State { Name = "Year", ParentStateMachine = timestamp };
            State month = new State { Name = "Month", ParentStateMachine = timestamp };
            State day = new State { Name = "Day", ParentStateMachine = timestamp };
            State hour = new State { Name = "Hour", ParentStateMachine = timestamp };
            State minute = new State { Name = "Minute", ParentStateMachine = timestamp };
            SmsTimeState second = new SmsTimeState { Name = "Second", ParentStateMachine = timestamp };

            timestamp.AddState(year);
            timestamp.AddState(month);
            timestamp.AddState(day);
            timestamp.AddState(hour);
            timestamp.AddState(minute);
            timestamp.AddState(second);

            timestamp.StartingStates.Add(year);
            timestamp.EndingStates.Add(second);

            AddTransition(year, month, 1d);
            AddTransition(month, day, 1d);
            AddTransition(day, hour, 1d);
            AddTransition(hour, minute, 1d);
            AddTransition(minute, second, 1d);

            int yearWeight = 0;

            //int startYr = Math.Max(2010, TimeConstants.START_YEAR);
            int startYr = TimeConstants.START_YEAR;
            for (int i = (startYr - 2000); i <= (TimeConstants.END_YEAR - 2000); i++)
            {
                var byteTest = byte.Parse(Convert.ToString(i), NumberStyles.HexNumber);
                var byteVal = Printer.SwapNibbles(byteTest);

                year.PossibleValueProbabilities[byteVal] = 1f + yearWeight;

                yearWeight++;
            }

            year.NormalizeProbabilities();

            for (int i = 1; i <= 12; i++)
            {
                var byteTest = byte.Parse(Convert.ToString(i), NumberStyles.HexNumber);
                var byteVal = Printer.SwapNibbles(byteTest);

                month.PossibleValueProbabilities[byteVal] = 1 / 12d;
            }

            for (int i = 1; i <= 31; i++)
            {
                var byteTest = byte.Parse(Convert.ToString(i), NumberStyles.HexNumber);
                var byteVal = Printer.SwapNibbles(byteTest);

                day.PossibleValueProbabilities[byteVal] = 1 / 31d;
            }

            for (int i = 0; i <= 23; i++)
            {
                var byteTest = byte.Parse(Convert.ToString(i), NumberStyles.HexNumber);
                var byteVal = Printer.SwapNibbles(byteTest);

                hour.PossibleValueProbabilities[byteVal] = 1 / 24d;
            }

            for (int i = 0; i <= 59; i++)
            {
                var byteTest = byte.Parse(Convert.ToString(i), NumberStyles.HexNumber);
                var byteVal = Printer.SwapNibbles(byteTest);

                minute.PossibleValueProbabilities[byteVal] = 1 / 60d;
                second.PossibleValueProbabilities[byteVal] = 1 / 60d;
            }

            return timestamp;
        }
        /// <summary>
        /// Gets the state machine for a UNIX timestamp.
        /// </summary>
        /// <param name="weight">Weight of TimeStamp_Unix state machine, among the set of state machines to be aggregated, governing a prior probability that the inferred sequence of states corresponds to TimeStamp_Unix state machine.</param>
        /// <returns></returns>
        public static StateMachine GetTimestamp_Unix(int weight)
        {
            var timestamp = new StateMachine { Name = MachineList.TimeStamp_Unix, _weight = weight };

            State unixTime1 = new State { Name = "UnixTime1", ParentStateMachine = timestamp };
            State unixTime2 = new State { Name = "UnixTime2", ParentStateMachine = timestamp };
            State unixTime3 = new State { Name = "UnixTime3", ParentStateMachine = timestamp };
            UnixTimeState unixTime4 = new UnixTimeState { Name = "UnixTime4", ParentStateMachine = timestamp };

            timestamp.AddState(unixTime1);
            timestamp.AddState(unixTime2);
            timestamp.AddState(unixTime3);
            timestamp.AddState(unixTime4); ;

            timestamp.StartingStates.Add(unixTime1);
            timestamp.EndingStates.Add(unixTime4);

            AddTransition(unixTime1, unixTime2, 1d);
            AddTransition(unixTime2, unixTime3, 1d);
            AddTransition(unixTime3, unixTime4, 1d);

            // BL
            DateTime epochTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
            //DateTime startTime = new DateTime(Math.Max(TimeConstants.START_YEAR, 2011), 1, 1, 0, 0, 0, DateTimeKind.Utc);
            DateTime startTime = new DateTime(TimeConstants.START_YEAR, 1, 1, 0, 0, 0, DateTimeKind.Utc);
            DateTime endTime = new DateTime(TimeConstants.END_YEAR, 12, 31, 23, 59, 59, DateTimeKind.Utc);
            uint startEpoch = (uint)(startTime - epochTime).TotalSeconds;
            uint endEpoch = (uint)(endTime - epochTime).TotalSeconds;
            byte[] startEpochBytes = BitConverter.GetBytes(startEpoch);
            byte[] endEpochBytes = BitConverter.GetBytes(endEpoch);
            // big-endian
            for (byte i = startEpochBytes[3]; i <= endEpochBytes[3]; i++)
            {
                unixTime1.PossibleValueProbabilities[i] = 1d;
            }
            unixTime1.NormalizeProbabilities();

            for (int i = 0; i < 256; i++)
            {
                unixTime2.PossibleValueProbabilities[i] = 1 / 256d;
                unixTime3.PossibleValueProbabilities[i] = 1 / 256d;
                unixTime4.PossibleValueProbabilities[i] = 1 / 256d;
            }
            return timestamp;
        }
        /// <summary>
        /// Gets the state machine for a ten digit international format phone number.
        /// </summary>        
        /// <returns></returns>
        public static StateMachine GetPhoneNumber_InternationalFormatTenDigit()
        {
            #region Prepend
            StateMachine prepend = new StateMachine { Name = MachineList.Prepend_InternationalTenDigit };

            State length = new State { Name = "Length", ParentStateMachine = prepend };
            State type = new State { Name = "Type", ParentStateMachine = prepend };

            prepend.AddState(length);
            prepend.AddState(type);

            prepend.StartingStates.Add(length);
            prepend.StartingStates.Add(type);
            prepend.EndingStates.Add(type);

            AddTransition(length, type, 1d);

            length.PossibleValueProbabilities[0x0a] = 0.5f;
            length.PossibleValueProbabilities[0x07] = 0.5f;
            type.PossibleValueProbabilities[0x81] = 0.5f;
            type.PossibleValueProbabilities[0x91] = 0.5f;
            #endregion

            #region PhoneNumber

            StateMachine phoneNumber = new StateMachine { Name = MachineList.PhoneNumber_InternationalFormatTenDigit };

            State digit21 = new State { Name = "Digit2_1", ParentStateMachine = phoneNumber };
            State digit43 = new State { Name = "Digit4_3", ParentStateMachine = phoneNumber };
            State digit65 = new State { Name = "Digit6_5", ParentStateMachine = phoneNumber };
            State digit87 = new State { Name = "Digit8_7", ParentStateMachine = phoneNumber };
            State digit109 = new State { Name = "Digit10_9", ParentStateMachine = phoneNumber };

            phoneNumber.AddState(digit21);
            phoneNumber.AddState(digit43);
            phoneNumber.AddState(digit65);
            phoneNumber.AddState(digit87);
            phoneNumber.AddState(digit109);

            phoneNumber.StartingStates.Add(digit21);
            phoneNumber.EndingStates.Add(digit109);

            AddTransition(digit21, digit43, 1d);
            AddTransition(digit43, digit65, 1d);
            AddTransition(digit65, digit87, 1d);
            AddTransition(digit87, digit109, 1d);

            //both nibbles can take 0-9
            for (byte j = 0x00; j <= 0x90; j += 0x10)
            {
                for (byte i = j; i <= j + 0x09; i++)
                {
                    digit65.PossibleValueProbabilities[i] = 1d;
                    digit87.PossibleValueProbabilities[i] = 1d;
                    digit109.PossibleValueProbabilities[i] = 1d;
                }
            }

            //leading nibble can take 0-9 and the other can take 2-9.
            for (byte j = 0x02; j <= 0x92; j += 0x10)
            {
                for (byte i = j; i <= j + 0x07; i++)
                {
                    digit21.PossibleValueProbabilities[i] = 1d;
                }
            }

            //leading nibble can take 2-9 and the other can take 0-9
            for (byte j = 0x20; j <= 0x90; j += 0x10)
            {
                for (byte i = j; i <= j + 0x09; i++)
                {
                    digit43.PossibleValueProbabilities[i] = 1d;
                }
            }

            digit21.NormalizeProbabilities();
            digit43.NormalizeProbabilities();
            digit65.NormalizeProbabilities();
            digit87.NormalizeProbabilities();
            digit109.NormalizeProbabilities();

            #endregion

            StateMachine phoneWithPrepend = new StateMachine { Name = MachineList.PhoneNumber_InternaltionalFormatWithPrepend };

            phoneWithPrepend.AddState(prepend._states);
            phoneWithPrepend.AddState(phoneNumber._states);

            phoneWithPrepend.StartingStates.AddRange(prepend.StartingStates);
            phoneWithPrepend.EndingStates = phoneNumber.EndingStates;

            AddTransitionToStateMachine(prepend, phoneNumber, 1d);

            return phoneWithPrepend;
        }
        /// <summary>
        /// Gets the state machine for ASCII string bigrams.
        /// </summary>
        /// <returns></returns>
        public static StateMachine GetAsciiString_Bigram()
        {
            StateMachine asciiString = new StateMachine { Name = MachineList.Text_AsciiBigram };

            BigramState asciiChar0 = new BigramState() { Name = "AsciiChar0", ParentStateMachine = asciiString };
            BigramState asciiChar05 = new BigramState() { Name = "AsciiChar0.5", ParentStateMachine = asciiString };
            //We have issue where the first letter of the ascii string is cut off. Hopefully this state will fix that.
            State asciiChar0_nonBigram = new State { Name = "AsciiChar0_nbg", ParentStateMachine = asciiString };
            State asciiChar1_nonBigram = new State { Name = "AsciiChar1_nbg", ParentStateMachine = asciiString };

            BigramState asciiChar1 = new BigramState() { Name = "AsciiChar1", ParentStateMachine = asciiString };
            BigramState asciiChar2 = new BigramState() { Name = "AsciiChar2", ParentStateMachine = asciiString };

            State printChar = new State { Name = "PrintChar", ParentStateMachine = asciiString };

            asciiString.AddState(printChar);
            asciiString.AddState(asciiChar0_nonBigram);
            asciiString.AddState(asciiChar05);
            asciiString.AddState(asciiChar0);
            asciiString.AddState(asciiChar1);
            asciiString.AddState(asciiChar2);
            asciiString.AddState(asciiChar1_nonBigram);
            asciiString.StartingStates.Add(asciiChar0);
            asciiString.StartingStates.Add(asciiChar0_nonBigram);
            asciiString.EndingStates.Add(asciiChar1);
            asciiString.EndingStates.Add(asciiChar2);
            asciiString.EndingStates.Add(printChar);

            AddTransition(asciiChar0_nonBigram, asciiChar05, 0.9d);
            AddTransition(asciiChar0_nonBigram, asciiChar1_nonBigram, 0.1d);
            AddTransition(asciiChar1_nonBigram, asciiChar05, 1d);
            AddTransition(asciiChar0, asciiChar05, 1d);
            AddTransition(asciiChar0, asciiChar1_nonBigram, 0.1d);
            AddTransition(asciiChar05, asciiChar1, 0.88d);
            AddTransition(asciiChar05, printChar, 0.11d);
            AddTransition(asciiChar1, asciiChar2, 0.68d);
            asciiChar1.RemainingProbability = 0.01d;
            AddTransition(asciiChar2, asciiChar1, 0.68d);
            asciiChar2.RemainingProbability = 0.01d;

            AddTransition(asciiChar1, printChar, 0.31d);
            AddTransition(asciiChar2, printChar, 0.31d);
            AddTransition(printChar, asciiChar1, 0.88d);
            AddTransition(printChar, printChar, 0.11d);
            printChar.RemainingProbability = 0.01d;

            // all printable characters
            for (int i = 32; i < 127; i++)
            {
                printChar.PossibleValueProbabilities[i] = 1d;
                asciiChar0_nonBigram.PossibleValueProbabilities[i] = 1d;
                asciiChar1_nonBigram.PossibleValueProbabilities[i] = 1d;
            }

            printChar.NormalizeProbabilities();
            asciiChar0_nonBigram.NormalizeProbabilities();

            return asciiString;
        }
        /// <summary>
        /// Gets the state machine for printable ASCII strings.
        /// </summary>
        /// <returns></returns>
        public static StateMachine GetAsciiPrintable()
        {
            StateMachine asciiString = new StateMachine { Name = MachineList.Text_AsciiPrintable };
            State asciiPart1 = new State { Name = "AsciiPart1", ParentStateMachine = asciiString };
            State asciiPart2 = new State { Name = "AsciiPart2", ParentStateMachine = asciiString };
            State asciiPart3 = new State { Name = "AsciiPart3", ParentStateMachine = asciiString };

            asciiString.AddState(asciiPart1);
            asciiString.AddState(asciiPart2);
            asciiString.AddState(asciiPart3);

            asciiString.StartingStates.Add(asciiPart1);
            asciiString.EndingStates.Add(asciiPart3);

            AddTransition(asciiPart1, asciiPart2, 1.0d);
            //AddTransition(asciiPart1, asciiPart1, 0.9d);
            AddTransition(asciiPart2, asciiPart3, 1.0d);
            //AddTransition(asciiPart2, asciiPart2, 0.9d);

            //Numbers
            for (byte i = 0x30; i < 0x39; i++)
            {
                asciiPart1.PossibleValueProbabilities[i] = 1d;
                asciiPart2.PossibleValueProbabilities[i] = 1d;
                asciiPart3.PossibleValueProbabilities[i] = 1d;
            }

            //Upper Case
            for (byte i = 0x41; i < 0x5a; i++)
            {
                asciiPart1.PossibleValueProbabilities[i] = 2d;
                asciiPart2.PossibleValueProbabilities[i] = 2d;
                asciiPart3.PossibleValueProbabilities[i] = 2d;
            }

            //Lower Case
            for (byte i = 0x61; i < 0x7a; i++)
            {
                asciiPart1.PossibleValueProbabilities[i] = 3d;
                asciiPart2.PossibleValueProbabilities[i] = 3d;
                asciiPart3.PossibleValueProbabilities[i] = 3d;
            }

            //Punct
            for (byte i = 0x20; i < 0x2F; i++)
            {
                asciiPart1.PossibleValueProbabilities[i] = 1d;
                asciiPart2.PossibleValueProbabilities[i] = 1d;
                asciiPart3.PossibleValueProbabilities[i] = 1d;
            }
            for (byte i = 0x3A; i < 0x40; i++)
            {
                asciiPart1.PossibleValueProbabilities[i] = 1d;
                asciiPart2.PossibleValueProbabilities[i] = 1d;
                asciiPart3.PossibleValueProbabilities[i] = 1d;
            }
            for (byte i = 0x5B; i < 0x60; i++)
            {
                asciiPart1.PossibleValueProbabilities[i] = 1d;
                asciiPart2.PossibleValueProbabilities[i] = 1d;
                asciiPart3.PossibleValueProbabilities[i] = 1d;
            }
            for (byte i = 0x7B; i < 0x7e; i++)
            {
                asciiPart1.PossibleValueProbabilities[i] = 1d;
                asciiPart2.PossibleValueProbabilities[i] = 1d;
                asciiPart3.PossibleValueProbabilities[i] = 1d;
            }

            asciiPart1.NormalizeProbabilities();
            asciiPart2.NormalizeProbabilities();
            asciiPart3.NormalizeProbabilities();

            return asciiString;
        }
        /// <summary>
        /// Gets the state machine for an eleven digit international format phone number.
        /// </summary>        
        /// <returns></returns>
        public static StateMachine GetPhoneNumber_InternationalFormatElevenDigit()
        {
            #region Prepend
            StateMachine prepend = new StateMachine { Name = MachineList.Prepend_InternationalElevenDigit };

            State length = new State { Name = "Length", ParentStateMachine = prepend };
            State type = new State { Name = "Type", ParentStateMachine = prepend };

            prepend.AddState(length);
            prepend.AddState(type);

            prepend.StartingStates.Add(length);
            prepend.StartingStates.Add(type);
            prepend.EndingStates.Add(type);

            AddTransition(length, type, 1d);

            length.PossibleValueProbabilities[0x0b] = 1f;
            length.PossibleValueProbabilities[0x08] = 1f;
            type.PossibleValueProbabilities[0x81] = 0.5f;
            type.PossibleValueProbabilities[0x91] = 0.5f;

            length.NormalizeProbabilities();
            type.NormalizeProbabilities();
            #endregion

            #region Phone Number

            StateMachine phoneNumber = new StateMachine { Name = MachineList.PhoneNumber_InternationalFormatElevenDigit };

            State digit21 = new State { Name = "Digit2_1", ParentStateMachine = phoneNumber };
            State digit43 = new State { Name = "Digit4_3", ParentStateMachine = phoneNumber };
            State digit65 = new State { Name = "Digit6_5", ParentStateMachine = phoneNumber };
            State digit87 = new State { Name = "Digit8_7", ParentStateMachine = phoneNumber };
            State digit109 = new State { Name = "Digit10_9", ParentStateMachine = phoneNumber };
            State digitF11 = new State { Name = "DigitF_11", ParentStateMachine = phoneNumber };

            phoneNumber.AddState(digit21);
            phoneNumber.AddState(digit43);
            phoneNumber.AddState(digit65);
            phoneNumber.AddState(digit87);
            phoneNumber.AddState(digit109);
            phoneNumber.AddState(digitF11);

            phoneNumber.StartingStates.Add(digit21);
            phoneNumber.EndingStates.Add(digitF11);

            AddTransition(digit21, digit43, 1d);
            AddTransition(digit43, digit65, 1d);
            AddTransition(digit65, digit87, 1d);
            AddTransition(digit87, digit109, 1d);
            AddTransition(digit109, digitF11, 1d);

            //Digit1 0x21, 0x31, ..., 0x91
            for (byte i = 0x21; i <= 0x91; i += 0x10)
            {
                digit21.PossibleValueProbabilities[i] = 1f;
            }

            for (byte j = 0x00; j <= 0x90; j += 0x10)
            {
                for (byte i = j; i <= j + 0x09; i++)
                {
                    digit43.PossibleValueProbabilities[i] = 1f;
                    digit87.PossibleValueProbabilities[i] = 1f;
                    digit109.PossibleValueProbabilities[i] = 1f;
                }
            }

            for (byte j = 0x02; j <= 0x92; j += 0x10)
            {
                for (byte i = j; i <= j + 0x07; i++)
                {
                    digit65.PossibleValueProbabilities[i] = 1f;
                }
            }

            for (byte i = 0xf0; i <= 0xf9; i++)
            {
                digitF11.PossibleValueProbabilities[i] = 1f;
            }

            digit21.NormalizeProbabilities();
            digit43.NormalizeProbabilities();
            digit65.NormalizeProbabilities();
            digit87.NormalizeProbabilities();
            digitF11.NormalizeProbabilities();

            #endregion

            StateMachine phoneWithPrepend = new StateMachine { Name = MachineList.PhoneNumber_InternaltionalFormatWithPrepend };

            phoneWithPrepend.AddState(prepend._states);
            phoneWithPrepend.AddState(phoneNumber._states);

            phoneWithPrepend.StartingStates.AddRange(prepend.StartingStates);
            phoneWithPrepend.EndingStates = phoneNumber.EndingStates;

            AddTransitionToStateMachine(prepend, phoneNumber, 1d);

            return phoneWithPrepend;
        }
        /// <summary>
        /// Gets the state machine for BCD numbers.
        /// Byte 0 - phone number length
        /// Byte 1 - type of address (129 or 145)
        /// Byte 2+ - BCD phone number (swapped nibbles)
        /// </summary>
        /// <returns></returns>
        public static StateMachine GetPhoneNumber_BCDWithPrepend()
        {
            StateMachine prepend = new StateMachine { Name = MachineList.Prepend_BCD };

            State length = new State { Name = "BCDLength", ParentStateMachine = prepend };
            for (int i = 4; i <= 11; i++)
            {
                length.PossibleValueProbabilities[i] = 1d;
            }
            length.NormalizeProbabilities();

            State toa = new State { Name = "BCDTOA", ParentStateMachine = prepend };
            toa.PossibleValueProbabilities[129] = 0.5d;
            toa.PossibleValueProbabilities[145] = 0.5d;

            prepend.AddState(length);
            prepend.AddState(toa);

            prepend.StartingStates.Add(length);
            //prepend.StartingStates.Add(toc);
            prepend.EndingStates.Add(toa);

            AddTransition(length, toa, 1d);

            StateMachine phoneNumber = new StateMachine { Name = MachineList.PhoneNumber_BCDPrepended };

            State digit1 = new State { Name = "BCDDigit1", ParentStateMachine = phoneNumber };
            BcdDigitState digitEven = new BcdDigitState { Name = "BCDDigitEven", ParentStateMachine = phoneNumber, LengthState = length };
            State digitOdd = new State { Name = "BCDDigitOdd", ParentStateMachine = phoneNumber };
            for (uint i = 0; i <= 9; i++)
            {
                for (uint n = 0; n <= 9; n++)
                {
                    uint x = ((n << 4) & 0xF0) | (i & 0x0F);
                    digit1.PossibleValueProbabilities[x] = 1d;
                    digitEven.PossibleValueProbabilities[x] = 1d;
                }
                uint z = 0xF0 | (i & 0x0F);
                digitOdd.PossibleValueProbabilities[z] = 1d;
            }
            digit1.NormalizeProbabilities();
            digitEven.NormalizeProbabilities();
            digitOdd.NormalizeProbabilities();

            phoneNumber.AddState(digit1);
            phoneNumber.AddState(digitEven);
            phoneNumber.AddState(digitOdd);

            phoneNumber.StartingStates.Add(digit1);
            phoneNumber.EndingStates.Add(digitEven);
            phoneNumber.EndingStates.Add(digitOdd);

            AddTransition(digit1, digitEven, 1d);
            AddTransition(digit1, digitOdd, 1d);
            AddTransition(digitEven, digitEven, 1d);
            AddTransition(digitEven, digitOdd, 1d);

            StateMachine phoneWithPrepend = new StateMachine { Name = MachineList.PhoneNumber_BCDWithPrepend };

            phoneWithPrepend.AddState(prepend._states);
            phoneWithPrepend.AddState(phoneNumber._states);

            phoneWithPrepend.StartingStates.AddRange(prepend.StartingStates);
            phoneWithPrepend.EndingStates = phoneNumber.EndingStates;

            AddTransitionToStateMachine(prepend, phoneNumber, 1d);

            return phoneWithPrepend;
        }
        /// <summary>
        /// Gets the state machine representing the end of a record on a Nokia phone.
        /// </summary>
        /// <param name="weight">Weight of NokiaRecordEnd state machine, among the set of state machines to be aggregated, governing a prior probability that the inferred sequence of states corresponds to NokiaRecordEnd state machine.</param>
        /// <returns></returns>
        public static StateMachine GetNokiaRecordEnd(int weight)
        {
            StateMachine recordEnd = new StateMachine { Name = MachineList.RecordEnd_Nokia, _weight = weight };

            State unknown1 = new State { Name = "Unknown1", ParentStateMachine = recordEnd, IsBinary = true };
            State unknown2 = new State { Name = "Unknown2", ParentStateMachine = recordEnd, IsBinary = true };
            State end1 = new State { Name = "End1", ParentStateMachine = recordEnd, IsBinary = false };
            State end2 = new State { Name = "End2", ParentStateMachine = recordEnd, IsBinary = false };

            recordEnd.AddState(unknown1);
            recordEnd.AddState(unknown2);
            recordEnd.AddState(end1);
            recordEnd.AddState(end2);

            recordEnd.StartingStates.Add(unknown1);
            recordEnd.EndingStates.Add(end2);

            AddTransition(unknown1, unknown2, 1f);
            AddTransition(unknown2, end1, 1f);
            AddTransition(end1, end2, 1f);

            end1.PossibleValueProbabilities[0xff] = 1f;
            end2.PossibleValueProbabilities[0xff] = 1f;

            for (int i = 0x00; i <= 0xfe; i++)
            {
                unknown1.PossibleValueProbabilities[i] = 1f;
                unknown2.PossibleValueProbabilities[i] = 1f;
            }

            unknown1.NormalizeProbabilities();
            unknown2.NormalizeProbabilities();

            return recordEnd;
        }
        public static StateMachine Get7BitString_WithLength(int weight)
        {
            var sevenBit = new StateMachine { Name = MachineList.Text_SevenBitWithLength, _weight = weight };
            var length = new State { Name = "Length", ParentStateMachine = sevenBit };
            var asciiChar = new SevenBitState() { Name = "SevenBit", LengthState = length, ParentStateMachine = sevenBit, AllValuesPossible = true };
            var endChar = new SevenBitState() { Name = "SevenBitEnd", LengthState = length, ParentStateMachine = sevenBit, AllValuesPossible = true, IsEnd = true };

            sevenBit.AddState(length);
            sevenBit.AddState(asciiChar);
            sevenBit.AddState(endChar);

            sevenBit.StartingStates.Add(length);
            sevenBit.EndingStates.Add(endChar);

            AddTransition(length, asciiChar, 1f);
            AddTransition(asciiChar, asciiChar, 0.4f);
            AddTransition(asciiChar, endChar, 0.6f);

            for (byte i = 0x02; i <= 0xa0; i++)
            {
                length.PossibleValueProbabilities[i] = 1f;
            }

            length.NormalizeProbabilities();

            return sevenBit;
        }
        /// <summary>
        /// Gets the state machine for the timestamp of a Nokia endian.
        /// </summary>
        /// <param name="weight">Weight of TimeStamp_NokiaEndian state machine, among the set of state machines to be aggregated, governing a prior probability that the inferred sequence of states corresponds to TimeStamp_NokiaEndian state machine.</param>
        /// <returns></returns>
        public static StateMachine GetTimestamp_NokiaEndian(int weight)
        {
            StateMachine timestamp = new StateMachine { Name = MachineList.TimeStamp_NokiaEndian, _weight = weight };

            State year1 = new State { Name = "Year1", ParentStateMachine = timestamp };
            State year2 = new State { Name = "Year2", ParentStateMachine = timestamp };

            State month = new State { Name = "Month", ParentStateMachine = timestamp };
            State day = new State { Name = "Day", ParentStateMachine = timestamp };
            State hour = new State { Name = "Hour", ParentStateMachine = timestamp };
            State min = new State { Name = "Min", ParentStateMachine = timestamp };
            NokiaEndianTimeState sec = new NokiaEndianTimeState { Name = "Sec", ParentStateMachine = timestamp };

            timestamp.AddState(year1);
            timestamp.AddState(year2);
            timestamp.AddState(month);
            timestamp.AddState(day);
            timestamp.AddState(hour);
            timestamp.AddState(min);
            timestamp.AddState(sec);

            timestamp.StartingStates.Add(year1);
            timestamp.EndingStates.Add(sec);

            AddTransition(year1, year2, 1d);
            AddTransition(year2, month, 1d);
            AddTransition(month, day, 1d);
            AddTransition(day, hour, 1d);
            AddTransition(hour, min, 1d);
            AddTransition(min, sec, 1d);

            // BL: Year: most significant byte rolls over in 2048
            // so we should be safe
            year2.PossibleValueProbabilities[0x07] = 1d;
            int start = TimeConstants.START_YEAR & 0xff;
            int end = TimeConstants.END_YEAR & 0xff;
            for (int i = start; i <= end; i++)
            {
                year1.PossibleValueProbabilities[i] = 1d;
            }
            year1.NormalizeProbabilities();

            //Month 01 - 12
            for (byte i = 0x01; i <= 0x0C; i++)
            {
                month.PossibleValueProbabilities[i] = 1 / 12d;
            }

            //Day 01 - 31
            for (byte i = 0x01; i <= 0x1F; i++)
            {
                day.PossibleValueProbabilities[i] = 1 / 31d;
            }

            //Hour 00 - 23
            for (byte i = 0x00; i <= 0x17; i++)
            {
                hour.PossibleValueProbabilities[i] = 1 / 24d;
            }

            //Minutes & Seconds 00-59
            for (byte i = 0x00; i <= 0x3B; i++)
            {
                min.PossibleValueProbabilities[i] = 1 / 60d;
                sec.PossibleValueProbabilities[i] = 1 / 60d;
            }
            return timestamp;
        }
        /// <summary>
        /// Gets the state machine for an eleven digit Nokia phone number.
        /// </summary>        
        /// <returns></returns>
        public static StateMachine GetPhoneNumber_NokiaElevenDigit()
        {
            StateMachine phoneNumber = new StateMachine { Name = MachineList.PhoneNumber_NokiaElevenDigit };

            State length = new State { Name = "Length", ParentStateMachine = phoneNumber };
            State digits12 = new State { Name = "Digit1_2", ParentStateMachine = phoneNumber };
            State digits34 = new State { Name = "Digit3_4", ParentStateMachine = phoneNumber };
            State digits56 = new State { Name = "Digit5_6", ParentStateMachine = phoneNumber };
            State digits78 = new State { Name = "Digit7_8", ParentStateMachine = phoneNumber };
            State digits910 = new State { Name = "Digit9_10", ParentStateMachine = phoneNumber };
            State digits110 = new State { Name = "Digit11_0", ParentStateMachine = phoneNumber };

            phoneNumber.AddState(length);
            phoneNumber.AddState(digits12);
            phoneNumber.AddState(digits34);
            phoneNumber.AddState(digits56);
            phoneNumber.AddState(digits78);
            phoneNumber.AddState(digits910);
            phoneNumber.AddState(digits110);

            phoneNumber.StartingStates.Add(length);
            phoneNumber.EndingStates.Add(digits110);

            AddTransition(length, digits12, 1d);
            AddTransition(digits12, digits34, 1d);
            AddTransition(digits34, digits56, 1d);
            AddTransition(digits56, digits78, 1d);
            AddTransition(digits78, digits910, 1d);
            AddTransition(digits910, digits110, 1d);

            length.PossibleValueProbabilities[0x0b] = 1d;
            length.PossibleValueProbabilities[0x11] = 1d;

            length.NormalizeProbabilities();

            for (byte i = 0x12; i <= 0x19; i++)
            {
                digits12.PossibleValueProbabilities[i] = 1 / 8d;
            }

            for (byte i = 0x11; i <= 0xA1; i += 0x10)
            {
                for (byte j = i; j <= i + 0x09; j++)
                {
                    digits34.PossibleValueProbabilities[j] = 0.01d;
                    digits78.PossibleValueProbabilities[j] = 0.01d;
                    digits910.PossibleValueProbabilities[j] = 0.01d;
                }
            }

            for (byte i = 0x21; i <= 0x91; i += 0x10)
            {
                for (byte j = i; j <= i + 0x09; j++)
                {
                    digits56.PossibleValueProbabilities[j] = 1 / 80d;
                }
            }

            for (byte i = 0x10; i <= 0xA0; i += 0x10)
            {
                digits110.PossibleValueProbabilities[i] = 0.1d;
            }

            return phoneNumber;
        }
        /// <summary>
        /// Gets the state machine for the timestamp of a Samsung phone.
        /// </summary>
        /// <param name="weight">Weight of TimeStamp_Samsung state machine, among the set of state machines to be aggregated, governing a prior probability that the inferred sequence of states corresponds to TimeStamp_Samsung state machine.</param>
        /// <returns></returns>
        public static StateMachine GetTimestamp_Samsung(int weight)
        {
            StateMachine timestamp = new StateMachine { Name = MachineList.TimeStamp_Samsung, _weight = weight };

            State byte1 = new State { Name = "Byte1", ParentStateMachine = timestamp };
            State byte2 = new State { Name = "Byte2", ParentStateMachine = timestamp };
            State byte3 = new State { Name = "Byte3", ParentStateMachine = timestamp };
            //State byte4 = new State { Name = "Byte4", ParentStateMachine = timestamp };
            SamsungTimeState byte4 = new SamsungTimeState { Name = "Byte4Checker", ParentStateMachine = timestamp };

            timestamp.AddState(byte1);
            timestamp.AddState(byte2);
            timestamp.AddState(byte3);
            timestamp.AddState(byte4);

            timestamp.StartingStates.Add(byte1);
            timestamp.EndingStates.Add(byte4);

            AddTransition(byte1, byte2, 1d);
            AddTransition(byte2, byte3, 1d);
            AddTransition(byte3, byte4, 1d);

            // BL
            // Last 12 bits represent year. Determine possible
            // last bytes (little-endian)
            int nyears = 0;
            for (int i = (TimeConstants.START_YEAR) >> 4; i <= (TimeConstants.END_YEAR) >> 4; i++)
            {
                byte4.PossibleValueProbabilities[i] = 1d;
                nyears++;
            }
            if (nyears > 1) byte4.NormalizeProbabilities();

            // Month (1-12) 4 bits and 4 bits of year.
            for (int yr = TimeConstants.START_YEAR; yr <= TimeConstants.END_YEAR; yr++)
            {
                for (byte mn = 1; mn <= 12; mn++)
                {
                    int x = ((yr & 0xf) << 4) | mn;
                    byte3.PossibleValueProbabilities[x] = 1d;
                }
            }
            byte3.NormalizeProbabilities();

            // BL
            // Minutes (0-59) 6 bits, Hours (0-23) 5 bits, Days (1-31) 5 bits
            for (int i = 0; i < 256; i++)
            {
                // 4 bits for day will not be zero.
                if ((i & 0xf8) == 0) continue;
                // 3 bits used by hours will not all be set.
                if ((i & 0x07) == 0x07) continue;
                byte2.PossibleValueProbabilities[i] = 1d;
            }
            byte2.NormalizeProbabilities();
            for (int i = 0; i < 256; i++)
            {
                // Don't permit minutes greater than 59
                if ((i & 0x3f) >= 60) continue;
                byte1.PossibleValueProbabilities[i] = 1d;
            }
            byte1.NormalizeProbabilities();

            return timestamp;
        }
        public static StateMachine GetPhoneNumber_NokiaNumberIndex(int weight)
        {
            var indexMachine = new StateMachine { Name = MachineList.PhoneNumberIndex_Nokia, _weight = weight };

            State index = new State { Name = "Number index", ParentStateMachine = indexMachine };

            indexMachine.AddState(index);
            indexMachine.StartingStates.Add(index);
            indexMachine.EndingStates.Add(index);

            for (byte i = 0x01; i < 0x10; i++)
            {
                index.PossibleValueProbabilities[i] = 1d;
            }

            index.NormalizeProbabilities();

            return indexMachine;
        }
        /// <summary>
        /// Gets the state machine for a timestamp correponding to an SMS.
        /// </summary>
        /// <param name="weight">Weight of TimeStamp_Sms state machine, among the set of state machines to be aggregated, governing a prior probability that the inferred sequence of states corresponds to TimeStamp_Sms state machine.</param>
        /// <returns></returns>
        public static StateMachine GetTimestamp_SmsGsm(int weight)
        {
            var timestamp = new StateMachine { Name = MachineList.TimeStamp_SmsGsm, _weight = weight };

            State year = new State { Name = "Year", ParentStateMachine = timestamp };
            State month = new State { Name = "Month", ParentStateMachine = timestamp };
            State day = new State { Name = "Day", ParentStateMachine = timestamp };
            State hour = new State { Name = "Hour", ParentStateMachine = timestamp };
            State minute = new State { Name = "Minute", ParentStateMachine = timestamp };
            State second = new State { Name = "Second", ParentStateMachine = timestamp };
            SmsGsmTimeState timezone = new SmsGsmTimeState { Name = "Timezone", ParentStateMachine = timestamp };

            timestamp.AddState(year);
            timestamp.AddState(month);
            timestamp.AddState(day);
            timestamp.AddState(hour);
            timestamp.AddState(minute);
            timestamp.AddState(second);
            timestamp.AddState(timezone);

            timestamp.StartingStates.Add(year);
            timestamp.EndingStates.Add(timezone);

            AddTransition(year, month, 1d);
            AddTransition(month, day, 1d);
            AddTransition(day, hour, 1d);
            AddTransition(hour, minute, 1d);
            AddTransition(minute, second, 1d);
            AddTransition(second, timezone, 1d);

            int yearWeight = 0;

            //int startYr = Math.Max(2010, TimeConstants.START_YEAR);
            int startYr = TimeConstants.START_YEAR;
            for (int i = (startYr - 2000); i <= (TimeConstants.END_YEAR - 2000); i++)
            {
                var byteTest = byte.Parse(Convert.ToString(i), NumberStyles.HexNumber);
                var byteVal = Printer.SwapNibbles(byteTest);

                year.PossibleValueProbabilities[byteVal] = 1f + yearWeight;

                yearWeight++;
            }

            year.NormalizeProbabilities();

            for (int i = 1; i <= 12; i++)
            {
                var byteTest = byte.Parse(Convert.ToString(i), NumberStyles.HexNumber);
                var byteVal = Printer.SwapNibbles(byteTest);

                month.PossibleValueProbabilities[byteVal] = 1 / 12d;
            }

            for (int i = 1; i <= 31; i++)
            {
                var byteTest = byte.Parse(Convert.ToString(i), NumberStyles.HexNumber);
                var byteVal = Printer.SwapNibbles(byteTest);

                day.PossibleValueProbabilities[byteVal] = 1 / 31d;
            }

            for (int i = 0; i <= 23; i++)
            {
                var byteTest = byte.Parse(Convert.ToString(i), NumberStyles.HexNumber);
                var byteVal = Printer.SwapNibbles(byteTest);

                hour.PossibleValueProbabilities[byteVal] = 1 / 24d;
            }

            for (int i = 0; i <= 59; i++)
            {
                var byteTest = byte.Parse(Convert.ToString(i), NumberStyles.HexNumber);
                var byteVal = Printer.SwapNibbles(byteTest);

                minute.PossibleValueProbabilities[byteVal] = 1 / 60d;
                second.PossibleValueProbabilities[byteVal] = 1 / 60d;
            }

            // Each interval represents a 15 minute GMT offset. If the most
            // significant bit (before swapping) is set, it's a negative value.
            for (int i = 0; i < 96; i++)
            {
                // Skip 15 minutes time zones, except Nepal's.
                if (((i % 2) == 1) && (i != 23)) continue;
                // Swapped BCD.
                byte byteVal = Printer.SwapNibbles(Printer.ByteFromNibbles(i / 10, i % 10));
                timezone.PossibleValueProbabilities[byteVal] = 1d;
                if ((i != 0) && (i != 23))
                {
                    // Mark negative (bytes are already swapped)
                    byteVal |= 0x08;
                    timezone.PossibleValueProbabilities[byteVal] = 1d;
                }
            }
            timezone.NormalizeProbabilities();

            return timestamp;
        }
        /// <summary>
        /// Gets the state machine for a twelve digit Nokia phone number.
        /// </summary>        
        /// <returns></returns>
        public static StateMachine GetPhoneNumber_NokiaTwelveDigit()
        {
            StateMachine phoneNumber = new StateMachine { Name = MachineList.PhoneNumber_NokiaTwelveDigit };

            State length = new State { Name = "Length", ParentStateMachine = phoneNumber };
            State digitsF1 = new State { Name = "DigitF_1", ParentStateMachine = phoneNumber };
            State digits23 = new State { Name = "Digit2_3", ParentStateMachine = phoneNumber };
            State digits45 = new State { Name = "Digit4_5", ParentStateMachine = phoneNumber };
            State digits67 = new State { Name = "Digit6_7", ParentStateMachine = phoneNumber };
            State digits89 = new State { Name = "Digit8_9", ParentStateMachine = phoneNumber };
            State digits1011 = new State { Name = "Digit10_11", ParentStateMachine = phoneNumber };

            phoneNumber.AddState(length);
            phoneNumber.AddState(digitsF1);
            phoneNumber.AddState(digits23);
            phoneNumber.AddState(digits45);
            phoneNumber.AddState(digits67);
            phoneNumber.AddState(digits89);
            phoneNumber.AddState(digits1011);

            phoneNumber.StartingStates.Add(length);
            phoneNumber.EndingStates.Add(digits1011);

            AddTransition(length, digitsF1, 1d);
            AddTransition(digitsF1, digits23, 1d);
            AddTransition(digits23, digits45, 1d);
            AddTransition(digits45, digits67, 1d);
            AddTransition(digits67, digits89, 1d);
            AddTransition(digits89, digits1011, 1d);

            length.PossibleValueProbabilities[0x0C] = 1d;
            length.PossibleValueProbabilities[0x11] = 1d;

            length.NormalizeProbabilities();

            digitsF1.PossibleValueProbabilities[0xf1] = 1d;

            for (byte i = 0x21; i <= 0x91; i += 0x10)
            {
                for (byte j = i; j <= i + 0x09; j++)
                {
                    digits23.PossibleValueProbabilities[j] = 1 / 80d;
                }
            }

            for (byte i = 0x12; i <= 0xa2; i += 0x10)
            {
                for (byte j = i; j <= i + 0x07; j++)
                {
                    digits45.PossibleValueProbabilities[j] = 1 / 80d;
                }
            }

            for (byte i = 0x11; i <= 0xa1; i += 0x10)
            {
                for (byte j = i; j <= i + 0x09; j++)
                {
                    digits67.PossibleValueProbabilities[j] = 0.01d;
                    digits89.PossibleValueProbabilities[j] = 0.01d;
                    digits1011.PossibleValueProbabilities[j] = 0.01d;
                }
            }

            return phoneNumber;
        }
        /// <summary>
        /// Gets the state machine corresponing to the Endian of a Unicode string.
        /// </summary>
        /// <returns></returns>
        public static StateMachine GetUnicodeStringEndian()
        {
            StateMachine unicodeString = new StateMachine { Name = MachineList.Text_UnicodeEndian };

            State uniNull0 = new State { Name = "UniNull0", ParentStateMachine = unicodeString };
            State uniChar0 = new State { Name = "UniChar0", ParentStateMachine = unicodeString };

            State uniNull1 = new State { Name = "UniNull1", ParentStateMachine = unicodeString };
            State uniChar1 = new State { Name = "UniChar1", ParentStateMachine = unicodeString };

            State uniNull2 = new State { Name = "UniNull2", ParentStateMachine = unicodeString };
            State uniChar2 = new State { Name = "UniChar2", ParentStateMachine = unicodeString };
            State uniChar2Punct = new State { Name = "UniChar2Punct", ParentStateMachine = unicodeString };

            unicodeString.AddState(uniNull0);
            unicodeString.AddState(uniChar0);
            unicodeString.AddState(uniNull1);
            unicodeString.AddState(uniChar1);
            unicodeString.AddState(uniNull2);
            unicodeString.AddState(uniChar2);
            unicodeString.AddState(uniChar2Punct);

            unicodeString.StartingStates.Add(uniChar0);
            unicodeString.EndingStates.Add(uniNull2);
            unicodeString.EndingStates.Add(uniNull1);

            AddTransition(uniChar0, uniNull0, 1f);
            AddTransition(uniNull0, uniChar1, 1f);
            AddTransition(uniChar1, uniNull1, 1f);
            AddTransition(uniNull1, uniChar2, 0.69f);
            AddTransition(uniNull1, uniChar2Punct, 0.30f);
            uniNull1.RemainingProbability = 0.1f;

            AddTransition(uniChar2, uniNull2, 1f);
            AddTransition(uniChar2Punct, uniNull2, 1f);

            AddTransition(uniNull2, uniChar2, 0.69f);
            AddTransition(uniNull2, uniChar2Punct, 0.30f);
            uniNull2.RemainingProbability = 0.01f;

            uniNull0.PossibleValueProbabilities[0x00] = 1d;
            uniNull1.PossibleValueProbabilities[0x00] = 1d;
            uniNull2.PossibleValueProbabilities[0x00] = 1d;

            uniChar1.PossibleValueProbabilities[0x20] = 1 / 54d;
            uniChar1.PossibleValueProbabilities[0x2D] = 1 / 54d;

            uniChar2.PossibleValueProbabilities[0x20] = 1 / 54d;
            uniChar2.PossibleValueProbabilities[0x2D] = 1 / 54d;

            //Upper case letters
            for (byte i = 0x41; i <= 0x5a; i++)
            {
                uniChar0.PossibleValueProbabilities[i] = 2d;
                uniChar1.PossibleValueProbabilities[i] = 1 / 54d;
                uniChar2.PossibleValueProbabilities[i] = 1 / 54d;
            }

            //Lower case letters
            for (byte i = 0x61; i <= 0x7a; i++)
            {
                uniChar0.PossibleValueProbabilities[i] = 1d;
                uniChar1.PossibleValueProbabilities[i] = 1 / 54d;
                uniChar2.PossibleValueProbabilities[i] = 1 / 54d;
            }

            //printable (non-alpha)
            for (int i = 33; i <= 64; i++)
            {
                uniChar2Punct.PossibleValueProbabilities[i] = 1d;
            }

            uniChar2Punct.PossibleValueProbabilities[0x20] = 1d;

            //printable (non-alpha)
            for (int i = 91; i <= 96; i++)
            {
                uniChar2Punct.PossibleValueProbabilities[i] = 1d;
            }

            //printable (non-alpha)
            for (int i = 123; i <= 127; i++)
            {
                uniChar2Punct.PossibleValueProbabilities[i] = 1d;
            }

            uniChar2Punct.NormalizeProbabilities();
            uniChar0.NormalizeProbabilities();

            return unicodeString;
        }
        /// <summary>
        /// Gets the state machine for a seven digit Samsung ASCII phone number.
        /// </summary>        
        /// <returns></returns>
        public static StateMachine GetPhoneNumber_SamsungSevenDigitAscii()
        {
            StateMachine phoneNumber = new StateMachine { Name = MachineList.PhoneNumber_SamsungSevenDigitAscii };

            State digit1 = new State { Name = "Digit1", ParentStateMachine = phoneNumber };
            State digit2 = new State { Name = "Digit2", ParentStateMachine = phoneNumber };
            State digit3 = new State { Name = "Digit3", ParentStateMachine = phoneNumber };
            State hiphen = new State { Name = "Hiphen", ParentStateMachine = phoneNumber };
            State digit4 = new State { Name = "Digit4", ParentStateMachine = phoneNumber };
            State digit5 = new State { Name = "Digit5", ParentStateMachine = phoneNumber };
            State digit6 = new State { Name = "Digit6", ParentStateMachine = phoneNumber };
            State digit7 = new State { Name = "Digit7", ParentStateMachine = phoneNumber };

            phoneNumber.AddState(digit1);
            phoneNumber.AddState(digit2);
            phoneNumber.AddState(digit3);
            phoneNumber.AddState(hiphen);
            phoneNumber.AddState(digit4);
            phoneNumber.AddState(digit5);
            phoneNumber.AddState(digit6);
            phoneNumber.AddState(digit7);

            phoneNumber.StartingStates.Add(digit1);
            phoneNumber.EndingStates.Add(digit7);

            AddTransition(digit1, digit2, 1d);
            AddTransition(digit2, digit3, 1d);
            AddTransition(digit3, digit4, 1 / 2d);
            AddTransition(digit3, hiphen, 1 / 2d);
            AddTransition(hiphen, digit4, 1d);
            AddTransition(digit4, digit5, 1d);
            AddTransition(digit5, digit6, 1d);
            AddTransition(digit6, digit7, 1d);

            for (byte i = 0x32; i <= 0x39; i++)
            {
                digit1.PossibleValueProbabilities[i] = 1 / 8d;
            }

            for (byte i = 0x30; i <= 0x39; i++)
            {
                digit2.PossibleValueProbabilities[i] = 0.1d;
                digit3.PossibleValueProbabilities[i] = 0.1d;
                digit5.PossibleValueProbabilities[i] = 0.1d;
                digit6.PossibleValueProbabilities[i] = 0.1d;
                digit7.PossibleValueProbabilities[i] = 0.1d;
                digit4.PossibleValueProbabilities[i] = 0.1d;
            }

            hiphen.PossibleValueProbabilities[0x2D] = 1d;

            digit1.NormalizeProbabilities();
            digit2.NormalizeProbabilities();
            digit3.NormalizeProbabilities();
            digit4.NormalizeProbabilities();
            digit5.NormalizeProbabilities();
            digit6.NormalizeProbabilities();
            digit7.NormalizeProbabilities();
            hiphen.NormalizeProbabilities();

            return phoneNumber;
        }
        /// <summary>
        /// Gets the meta state machine for a generic Call Log.
        /// </summary>
        /// <param name="weight">Weight of CallLogGeneric state machine, among the set of state machines to be aggregated, governing a prior probability that the inferred sequence of states corresponds to CallLogGeneric state machine.</param>
        /// <returns></returns>
        public static StateMachine GetMeta_CallLogGeneric(int weight)
        {
            StateMachine metaCallLog = new StateMachine { Name = MachineList.Meta_CallLogGeneric, _weight = weight };

            State textStart = new State { Name = "Text", ParentStateMachine = metaCallLog };
            State text = new State { Name = "Text", ParentStateMachine = metaCallLog };
            State binaryA = new State { Name = "Binary", ParentStateMachine = metaCallLog, IsBinary = true };
            State binaryB = new State { Name = "Binary", ParentStateMachine = metaCallLog, IsBinary = true };
            State phoneNumber = new State { Name = "PhoneNumber", ParentStateMachine = metaCallLog };
            State phoneNumberStartWText = new State { Name = "PhoneNumber", ParentStateMachine = metaCallLog };
            State phoneNumberStart = new State { Name = "PhoneNumber", ParentStateMachine = metaCallLog };
            State binary2 = new State { Name = "Binary2", ParentStateMachine = metaCallLog, IsBinary = true };
            State timeStamp = new State { Name = "TimeStamp", ParentStateMachine = metaCallLog };

            metaCallLog.AddState(text);
            metaCallLog.AddState(binaryA);
            metaCallLog.AddState(binaryB);
            metaCallLog.AddState(phoneNumber);
            metaCallLog.AddState(binary2);
            metaCallLog.AddState(timeStamp);
            metaCallLog.AddState(textStart);
            metaCallLog.AddState(phoneNumberStartWText);
            metaCallLog.AddState(phoneNumberStart);

            metaCallLog.StartingStates.Add(textStart);
            metaCallLog.StartingStates.Add(phoneNumberStart);
            metaCallLog.StartingStates.Add(phoneNumberStartWText);
            metaCallLog.EndingStates.Add(timeStamp);

            //Starting path txt -> number
            AddTransition(textStart, binaryA, 1f);
            AddTransition(binaryA, phoneNumber, 0.99f);
            AddTransition(binaryA, binaryA, 0.01f);
            AddTransition(phoneNumber, binary2, 1f);

            //starting path number -> txt
            AddTransition(phoneNumberStartWText, binaryB, 1f);
            AddTransition(binaryB, text, 0.99f);
            AddTransition(binaryB, binaryB, 0.01f);
            AddTransition(text, binary2, 1f);

            //starting path number -> no text
            AddTransition(phoneNumberStart, binary2, 1f);

            AddTransition(binary2, timeStamp, 0.99f);
            AddTransition(binary2, binary2, 0.01f);
            AddTransition(timeStamp, binary2, 0.9f);
            timeStamp.RemainingProbability = 0.1f;

            for (int i = 0; i < 256; i++)
            {
                binaryA.PossibleValueProbabilities[i] = 1f;
                binaryB.PossibleValueProbabilities[i] = 1f;
                binary2.PossibleValueProbabilities[i] = 1f;
            }

            binaryA.PossibleValueProbabilities[(byte)MetaMachine.PhoneNumber] = 0f;
            binaryA.PossibleValueProbabilities[(byte)MetaMachine.Text] = 0f;
            binaryA.PossibleValueProbabilities[(byte)MetaMachine.TimeStamp] = 0f;
            binaryA.PossibleValueProbabilities[(byte)MetaMachine.BinaryLarge] = 0f;

            binaryB.PossibleValueProbabilities[(byte)MetaMachine.PhoneNumber] = 0f;
            binaryB.PossibleValueProbabilities[(byte)MetaMachine.Text] = 0f;
            binaryB.PossibleValueProbabilities[(byte)MetaMachine.TimeStamp] = 0f;
            binaryB.PossibleValueProbabilities[(byte)MetaMachine.BinaryLarge] = 0f;

            binary2.PossibleValueProbabilities[(byte)MetaMachine.PhoneNumber] = 0f;
            binary2.PossibleValueProbabilities[(byte)MetaMachine.Text] = 0f;
            binary2.PossibleValueProbabilities[(byte)MetaMachine.TimeStamp] = 0f;
            binary2.PossibleValueProbabilities[(byte)MetaMachine.BinaryLarge] = 0f;

            binaryA.NormalizeProbabilities();
            binaryB.NormalizeProbabilities();
            binary2.NormalizeProbabilities();

            text.PossibleValueProbabilities[(byte)MetaMachine.Text] = 1f;
            textStart.PossibleValueProbabilities[(byte)MetaMachine.Text] = 1f;
            phoneNumber.PossibleValueProbabilities[(byte)MetaMachine.PhoneNumber] = 1f;
            phoneNumberStart.PossibleValueProbabilities[(byte)MetaMachine.PhoneNumber] = 1f;
            phoneNumberStartWText.PossibleValueProbabilities[(byte)MetaMachine.PhoneNumber] = 1f;
            timeStamp.PossibleValueProbabilities[(byte)MetaMachine.TimeStamp] = 1f;

            return metaCallLog;
        }
        /// <summary>
        /// Gets the meta state machine for a generic Call Log.
        /// </summary>
        /// <param name="weight">Weight of CallLogGeneric3 state machine, among the set of state machines to be aggregated, governing a prior probability that the inferred sequence of states corresponds to CallLogGeneric3 state machine.</param>
        /// <returns></returns>
        public static StateMachine GetMeta_CallLogGeneric3(int weight)
        {
            StateMachine metaCallLog = new StateMachine { Name = MachineList.Meta_CallLogGeneric3, _weight = weight };
            State binary1 = new State { Name = "Binary", ParentStateMachine = metaCallLog, IsBinary = true };
            State binaryX = new State { Name = "Binary", ParentStateMachine = metaCallLog, IsBinary = true };
            State phoneNumber1 = new State { Name = "PhoneNumber", ParentStateMachine = metaCallLog };
            State timeStamp1 = new State { Name = "TimeStamp", ParentStateMachine = metaCallLog };

            metaCallLog.AddState(binary1);
            metaCallLog.AddState(binaryX);
            metaCallLog.AddState(phoneNumber1);
            metaCallLog.AddState(timeStamp1);

            metaCallLog.StartingStates.Add(timeStamp1);
            metaCallLog.EndingStates.Add(phoneNumber1);

            //Starting path timestamp -> number
            AddTransition(timeStamp1, binary1, 1f);
            AddTransition(binary1, phoneNumber1, 1f);
            //AddTransition(binary1, binary1, 0.01f);
            AddTransition(phoneNumber1, binaryX, 1f);

            for (int i = 0; i < 256; i++)
            {
                binary1.PossibleValueProbabilities[i] = 1f;
                binaryX.PossibleValueProbabilities[i] = 1f;
            }

            binary1.PossibleValueProbabilities[(byte)MetaMachine.PhoneNumber] = 0f;
            binary1.PossibleValueProbabilities[(byte)MetaMachine.Text] = 0f;
            binary1.PossibleValueProbabilities[(byte)MetaMachine.TimeStamp] = 0f;
            binary1.PossibleValueProbabilities[(byte)MetaMachine.BinaryLarge] = 0f;

            binaryX.PossibleValueProbabilities[(byte)MetaMachine.PhoneNumber] = 0f;
            binaryX.PossibleValueProbabilities[(byte)MetaMachine.Text] = 0f;
            binaryX.PossibleValueProbabilities[(byte)MetaMachine.TimeStamp] = 0f;
            binaryX.PossibleValueProbabilities[(byte)MetaMachine.BinaryLarge] = 0f;

            binary1.NormalizeProbabilities();
            binaryX.NormalizeProbabilities();

            phoneNumber1.PossibleValueProbabilities[(byte)MetaMachine.PhoneNumber] = 1f;
            timeStamp1.PossibleValueProbabilities[(byte)MetaMachine.TimeStamp] = 1f;

            return metaCallLog;
        }