Exemple #1
0
            /// <summary>
            /// Осуществляет декодирование алгоритмом Левенштейна.
            /// </summary>
            /// <param name="Source"></param>
            /// <returns></returns>
            public static int Decode(ByteSet Source)
            {
                int c = 0;

                while (Source.Value[c] != 0)
                {
                    c++;
                }
                if (c == 0)
                {
                    return(0);
                }
                Source.Cut(0, c + 1);
                int N = 1;
                int P = c - 1;

                while (P != 0)
                {
                    ByteSet buffer = Source.Cut(0, N);
                    buffer.Put(0, 1);
                    N = 0;
                    for (int i = buffer.Value.Length - 1; i >= 0; i--)
                    {
                        if (buffer.Value[i] == 1)
                        {
                            N += (int)Math.Pow(2, buffer.Length - 1 - i);
                        }
                    }
                    P--;
                }
                return(N);
            }
Exemple #2
0
            /// <summary>
            /// Осуществляет кодирование алгоритмом Левенштейна.
            /// </summary>
            /// <param name="Source"></param>
            /// <returns></returns>
            public static string Encode(int Source)
            {
                if (Source == 0)
                {
                    return("0");
                }
                ByteSet Result = new ByteSet();
                int     buffer = Source;
                int     C      = 1;

                while (buffer != 0)
                {
                    bool[] Binary = Misc.GetBinaryArray(buffer).Skip(1).ToArray();
                    buffer = Binary.Length;
                    if (buffer == 0)
                    {
                        break;
                    }
                    Result.Put(0, Binary.Select(bol => bol ? (byte)1 : (byte)0).ToArray());
                    C++;
                }

                Result.Put(0, Enumerable.Repeat((byte)1, C - 1).Concat(new[] { (byte)0 }).ToArray());
                return(Result.ToString());
            }
Exemple #3
0
            /// <summary>
            /// Осуществляет кодирование Шеннона.
            /// </summary>
            /// <param name="Probabilities">Массив вероятностей исходного алфавита, отсортированный в порядке убывания частот.</param>
            /// <param name="AverageLength">Средняя длина получаемых кодовых слов.</param>
            /// <returns>Массив кодов слов, поставленный в соответствие каждой букве исходного алфавита в порядке убывания частот</returns>
            public static ByteSet[] Encode(double[] Probabilities, out double AverageLength)
            {
                AverageLength = 0;
                ByteSet[] Result = new ByteSet[Probabilities.Length];
                double[]  Probs  = Probabilities.OrderByDescending(val => val).ToArray();
                double    Sum    = 0;

                for (int i = 0; i < Probs.Length; i++)
                {
                    Result[i] = new ByteSet(Misc.DoubleFractToString(Sum, GetL(Probs[i])));
                    Sum      += Probs[i];
                }

                AverageLength += Probabilities.Select((t, i) => t * Result[i].Length).Sum();
                return(Result);
            }
Exemple #4
0
            /// <summary>
            /// Вырезает бит на нужной позиции.
            /// </summary>
            /// <param name="TargetIndex">Индекс, по которому необходимо вырезать бит.</param>
            internal ByteSet CutAt(int TargetIndex)
            {
                ByteSet Result = new ByteSet();

                byte[] buffer = new byte[Value.Length - 1];
                for (int i = 0; i < TargetIndex; i++)
                {
                    buffer[i] = Value[i];
                }
                Result.Append(Value[TargetIndex]);
                for (int i = TargetIndex + 1; i < Value.Length; i++)
                {
                    buffer[i - 1] = Value[i];
                }
                Value = buffer;
                return(Result);
            }
Exemple #5
0
            /// <summary>
            /// Осуществляет кодирование алгоритмом Гилберта-Мура.
            /// </summary>
            /// <param name="Probabilities">Массив вероятностей исходного алфавита, отсортированный в порядке следования букв в исходном тексте.</param>
            /// <param name="AverageLength">Средняя длина получаемых кодовых слов.</param>
            /// <returns>Массив кодов слов, поставленный в соответствие каждой букве исходного алфавита в порядке следования букв в исходном тексте.</returns>
            public static ByteSet[] Encode(double[] Probabilities, out double AverageLength)
            {
                AverageLength = 0;
                double[]  Q      = new double[Probabilities.Length];
                ByteSet[] Result = new ByteSet[Probabilities.Length];

                for (int i = 0; i < Q.Length; i++)
                {
                    Q[i]     += Probabilities[i] / 2;
                    Result[i] = new ByteSet(Misc.DoubleFractToString(Q[i],
                                                                     (int)Math.Ceiling(-Math.Log(Probabilities[i], 2)) + 1));
                    for (int j = i + 1; j < Probabilities.Length; j++)
                    {
                        Q[j] += Probabilities[i];
                    }
                }

                AverageLength = Result.Select((res, ind) => res.Length * Probabilities[ind]).Sum();
                return(Result);
            }
Exemple #6
0
            /// <summary>
            /// Вырезает нужное число бит начиная с указанной позиции.
            /// </summary>
            /// <param name="StartIndex">Индекс, начиная с которого необходимо вырезать биты.</param>
            /// <param name="Length">Число вырезаемых бит.</param>
            internal ByteSet Cut(int StartIndex, int Length)
            {
                ByteSet Result = new ByteSet();

                byte[] buffer = new byte[Value.Length - Length];
                for (int i = 0; i < StartIndex; i++)
                {
                    buffer[i] = Value[i];
                }
                for (int i = 0; i < Length; i++)
                {
                    Result.Append(Value[StartIndex + i]);
                }
                for (int i = StartIndex + Length; i < Value.Length; i++)
                {
                    buffer[i - Length] = Value[i];
                }
                Value = buffer;
                return(Result);
            }
Exemple #7
0
 /// <summary>
 ///     Инициализирует копию указанного вектора.
 /// </summary>
 /// <param name="Other">Вектор ,от которого необходимо взять копию.</param>
 public ByteSet(ByteSet Other) : this(Other.Value)
 {
 }
Exemple #8
0
            /// <summary>
            ///     Осуществляет генерацию кодов, подходящим заданным частотам так, чтобы добиться наименьшей средней длины сообщения.
            /// </summary>
            /// <param name="Probabilities">Массив - частотный анализ исходного алфавита.</param>
            /// <param name="k">Система счисления, в которой будет произведено кодирование.</param>
            /// <param name="AverageLength">Вычисленная в процессе генерации кодов средняя длина сообщения.</param>
            /// <returns>
            ///     Массив <see cref="ByteSet" />[], содержащий в себе коды, расположенные в соответствии введенным частотам в
            ///     порядке убывания.
            /// </returns>
            public static ByteSet[] GetCodes(double[] Probabilities, int k, out double AverageLength)
            {
                AverageLength = 0;
                if (k >= Probabilities.Length)
                {
                    ByteSet[] answer = new ByteSet[Probabilities.Length];
                    for (int i = 0; i < Probabilities.Length; i++)
                    {
                        answer[i] = new ByteSet {
                            Value = new[] { (byte)i }
                        };
                        AverageLength += Probabilities[i];
                    }

                    return(answer);
                }

                //k - это число частей, на которые нам необходимо разбивать вероятности
                double[] ProbCop = new double[Probabilities.Length];
                Probabilities.CopyTo(ProbCop, 0);
                Array.Sort(ProbCop, (d, d1) => Math.Sign((d1 - d)));
                //отсортировали свою копию массива в порядке убывания вероятностей

                Stack <int> Insertions = new Stack <int>();
                //n - мощность исходного алфавита (кол-во вероятностей, которое на вход дали)
                //k - мощность конечного алфавита (система счисления)
                //ПЕРВАЯ СВЕРТКА
                int FirstConvolutionLength;

                if (k == 2)
                {
                    FirstConvolutionLength = 2;
                }
                else
                {
                    Comparison.LinearComparison k0 = new Comparison.LinearComparison(ProbCop.Length, k - 1);
                    if (k0.A == 0)
                    {
                        FirstConvolutionLength = k - 1;
                    }
                    else if (k0.A == 1)
                    {
                        FirstConvolutionLength = k;
                    }
                    else
                    {
                        FirstConvolutionLength = (int)k0.A;
                    }
                }

                double Sum = ProbCop.Skip(ProbCop.Length - FirstConvolutionLength).Sum();

                Sum = Math.Round(Sum, 3);
                int Index        = 0;
                int ResultLength = ProbCop.Length - FirstConvolutionLength + 1;

                while (ProbCop[Index] >= Sum && Index < ResultLength)
                {
                    Index++;
                }
                Insertions.Push(Index);
                List <double> bufferProb = new List <double>(ProbCop);

                bufferProb.Insert(Index, Sum);
                ProbCop = bufferProb.Take(ResultLength).ToArray();
                //Последующие свертки
                while (ProbCop.Length != k)
                {
                    Sum = ProbCop.Skip(ProbCop.Length - k).Sum();
                    Sum = Math.Round(Sum, 3);
                    //вычислили сумму последних k элементов

                    //надо определить, на какой индекс будем вставлять
                    Index        = 0;
                    ResultLength = ProbCop.Length - k + 1;
                    while (ProbCop[Index] >= Sum && Index < ResultLength)
                    {
                        Index++;
                    }
                    //нашли индекс, на который необходимо вставить полученную сумму

                    Insertions.Push(Index);
                    bufferProb = new List <double>(ProbCop);
                    bufferProb.Insert(Index, Sum);
                    ProbCop = bufferProb.Take(ResultLength).ToArray();
                }

                List <ByteSet> Answer = new List <ByteSet>();

                for (int i = 0; i < ProbCop.Length; i++)
                {
                    Answer.Add(new ByteSet {
                        Value = new[] { (byte)i }
                    });
                }

                int            Moving;
                List <ByteSet> buffer;

                //Все восстановления, кроме последнего
                while (Insertions.Count != 1)
                {
                    Moving = Insertions.Pop();
                    //узнали о перестановке
                    buffer = new List <ByteSet>(Answer);
                    buffer.RemoveAt(Moving);
                    for (int i = 0; i < k; i++)
                    {
                        buffer.Add(new ByteSet(Answer[Moving]));
                        buffer.Last().Append((byte)i);
                    }

                    Answer = buffer;
                }

                //ВОССТАНОВЛЕНИЕ ПОСЛЕДНЕЙ СВЕРТКИ
                Moving = Insertions.Pop();
                //узнали о перестановке
                buffer = new List <ByteSet>(Answer);
                buffer.RemoveAt(Moving);
                for (int i = 0; i < FirstConvolutionLength; i++)
                {
                    buffer.Add(new ByteSet(Answer[Moving]));
                    buffer.Last().Append((byte)i);
                }

                Answer = buffer;

                AverageLength += Probabilities.Select((t, i) => t * Answer[i].Length).Sum();
                return(Answer.ToArray());
            }