From 018bac4688fc22f9cb9415be03f44de2743f5f88 Mon Sep 17 00:00:00 2001 From: Andrew Date: Fri, 29 Nov 2019 08:11:27 +0700 Subject: [PATCH] 1sem matlab 05 --- 1sem/octave/05/alph_entropy.m | 4 +++ 1sem/octave/05/alph_redundancy.m | 5 ++++ 1sem/octave/05/calc_info.m | 25 ++++++++++++++++ 1sem/octave/05/gen_msg.m | 49 ++++++++++++++++++++++++++++++++ 1sem/octave/05/main.m | 27 ++++++++++++++++++ 5 files changed, 110 insertions(+) create mode 100644 1sem/octave/05/alph_entropy.m create mode 100644 1sem/octave/05/alph_redundancy.m create mode 100644 1sem/octave/05/calc_info.m create mode 100644 1sem/octave/05/gen_msg.m create mode 100644 1sem/octave/05/main.m diff --git a/1sem/octave/05/alph_entropy.m b/1sem/octave/05/alph_entropy.m new file mode 100644 index 0000000..be9de2a --- /dev/null +++ b/1sem/octave/05/alph_entropy.m @@ -0,0 +1,4 @@ +function [h] = alph_entropy(P); + P = P(P ~= 0); + h = -sum(P.*log2(P)); +endfunction; diff --git a/1sem/octave/05/alph_redundancy.m b/1sem/octave/05/alph_redundancy.m new file mode 100644 index 0000000..2a762d6 --- /dev/null +++ b/1sem/octave/05/alph_redundancy.m @@ -0,0 +1,5 @@ +function [r] = alph_redundancy(P); + ent = alph_entropy(P); + mx_ent = log2(length(P)) + r = 1 - ent/mx_ent; +endfunction; diff --git a/1sem/octave/05/calc_info.m b/1sem/octave/05/calc_info.m new file mode 100644 index 0000000..0b07748 --- /dev/null +++ b/1sem/octave/05/calc_info.m @@ -0,0 +1,25 @@ +function [b,n] = calc_info(msg, alph, alph_p) + l_alph = length(alph); + l_alph_p = length(alph_p); + l_msg = length(msg); + if l_alph ~= l_alph_p; + error("[ERR] length(alph) != length(alph_p) (%d != %d)", l_alph, l_alph_p) + endif + + b = 0; + for i = 1:l_msg + flag = false; + for j = 1:l_alph + if msg(i) == alph(j) + flag = true; + b -= log(alph_p(j)); + break + endif + endfor + if ~flag + warning("[WARN] Symbol '%s' (at pos. %d from msg) not found in alphabet", msg(i), i) + endif + endfor + + n = l_msg * log2(l_alph); +endfunction diff --git a/1sem/octave/05/gen_msg.m b/1sem/octave/05/gen_msg.m new file mode 100644 index 0000000..a2f793c --- /dev/null +++ b/1sem/octave/05/gen_msg.m @@ -0,0 +1,49 @@ +% Программа генерации случайного сообщения в алфавите, содержащем не более 36 символов: 0, ..., 9, A, ..., Z. +% Автор: Кирилл Владимирович Пушкарёв. +% Дата: 26 октября 2019 г. +% Версия: 0.2 +% Параметры: +% p - вектор, содержащий от 2 до 36 неотрицательных чисел. +% Вероятности символов алфавита. +% len - целое число. +% Длина сообщения. +function msg = gen_msg(p, len) + % Создаём вектор символов алфавита 0, ..., 9, A, ..., Z + alph = ['0':'9' 'A':'Z']; + % Если p не вектор, ошибка + if ~isvector(p) + error('p must be a vector') + end + % Если длина вектора p больше длины alph, ошибка + if length(p) > length(alph) + % Выводим сообщение об ошибке, подставляя в него целые числа (%d) — длины векторов + error('p is too long (%d > %d)', length(p), length(alph)); + end + % Если длина вектора p меньше 2, ошибка + if length(p) < 2 + error('p is too short (%d < 2)', length(p)); + end + % Если длина не одно число, ошибка + if ~isscalar(len) + error('len must be a scalar') + end + % Если длина меньше 1, ошибка + if len < 1 + error('len is too small (%d < 1)', len) + end + % Создаём пустую строку для записи сообщения + msg = ''; + % Цикл по i от 1 до len + for i = 1:len + % Заносим случайно выбранный с заданными вероятностями символ в msg + msg(i) = alph(rand_discr(p)); + end +end + +% Функция генерации целого случайного числа i с вероятностью p(i). +% Параметры: +% p - вектор неотрицательных чисел, сумма элементов которого равна 1. +% Вероятности. +function r = rand_discr(p) + r = sum(cumsum(p) < rand()) + 1; +end diff --git a/1sem/octave/05/main.m b/1sem/octave/05/main.m new file mode 100644 index 0000000..c307dd6 --- /dev/null +++ b/1sem/octave/05/main.m @@ -0,0 +1,27 @@ +#stage 3 +V=33 +rand("state", V) + +#stage 4 +alph = char([48:57 65:70]); +r = rand(1, 16); +ralph = r./sum(r); +save -ascii "ralph.txt" ralph; + +#stage 5 +h = alph_entropy(ralph); +r = alph_redundancy(ralph); + +#stage 6 +msg = gen_msg(ralph, 100); +dlmwrite("msg.txt", msg, ''); + +#stage 7 +[b, n] = calc_info(msg, alph, ralph); + +#stage 8 +avg_b = b / length(msg); + +#stage 9 +results = [b, n, avg_b, h, r] +save -ascii "results.txt" results;