Документация Engee

Создание последовательности мотивов

MotifSequenceGenerator

Этот модуль генерирует случайные последовательности мотивов с тем условием, что последовательность имеет некоторую общую длину ℓ такую, что q - δq ≤ ℓ ≤ q + δq. Основные функциональные возможности обеспечиваются функцией random_sequence.

random_sequence(motifs::Vector{M}, q, limits, translate, δq = 0; kwargs...)

Создает случайную последовательность мотивов типа M, с ограничением, что последовательность имеет «длину» точно в пределах q - δq ≤ ℓ ≤ q + δq. Возвращает саму последовательность, а также последовательность индексов мотивов motifs, использованных для ее создания. В качестве аргумента ключевого слова может быть задан вектор вероятностей weights, который определяет вероятность выборки для каждого элемента motifs для созданной исходной последовательности.

Под «длиной» здесь понимается абстрактная длина, определяемая структурой M на основе функций limits и translate. Она не связана с количеством элементов.

M может быть любой структурой, к которой применимы две функции:

  • limits(motif): некоторая функция, которая для заданного мотива motif возвращает (start, fine) мотива в тех же единицах, что и q. Эта функция определяет величину длины, которая просто равна fine - start.

  • translate(motif, t): некоторая функция, которая для заданного мотива motif возвращает новый мотив, преобразованный на величину t (отрицательную или положительную) в тех же единицах, что и q.

Другие именованные аргументы

Полное описание алгоритма см. в исходном коде (используйте @which).

  • tries = 5: допустимое количество исходных случайных последовательностей.

  • taulcut = 2: максимальное количество исключений элемента из первоначального предположения.

  • summands = 3: максимальное количество мотивов, которые можно объединить для получения полной последовательности.

Простой пример

В этом примере показано, как модуль MotifSequenceGenerator работает простой структурой struct. Более приближенный к реальности и гораздо более сложный пример см. в разделе Пример с использованием музыкальных нот.

Предположим, что мы хотим создать случайную последовательность «возгласов», которые описываются структурой struct.

struct Shout
  shout::String
  start::Int
end

Давайте сначала создадим вектор возгласов, который будет использоваться в качестве набора возможных мотивов для создания случайной последовательности:

using Random
shouts = [Shout(uppercase(randstring(rand(3:5))), rand(1:100)) for k in 1:5]
5-element Vector{Main.Shout}:
 Main.Shout("0APP", 85)
 Main.Shout("I4X", 100)
 Main.Shout("FVZSV", 82)
 Main.Shout("F6N", 77)
 Main.Shout("PFOFW", 25)

Обратите внимание, что в данный момент значения поля .start объекта Shout не важны. MotifSequenceGenerator преобразует все мотивы так, чтобы они начинались в точке 0.

Теперь, чтобы создать случайную последовательность, нужно определить две сущности:

shoutlimits(s::Shout) = (s.start, s.start + length(s.shout) + 1);

shouttranslate(s::Shout, n) = Shout(s.shout, s.start + n);
shouttranslate (generic function with 1 method)

Это означает, что мы принимаем тот факт, что временная длина Shout равна length(s.shout) + 1.

Теперь мы можем создавать случайные последовательности возгласов общей длиной ровно q:

using MotifSequenceGenerator
q = 30
sequence, idxs = random_sequence(shouts, q, shoutlimits, shouttranslate)
sequence
6-element Vector{Main.Shout}:
 Main.Shout("PFOFW", 0)
 Main.Shout("F6N", 6)
 Main.Shout("F6N", 10)
 Main.Shout("PFOFW", 14)
 Main.Shout("I4X", 20)
 Main.Shout("FVZSV", 24)
sequence, idxs = random_sequence(shouts, q, shoutlimits, shouttranslate)
sequence
6-element Vector{Main.Shout}:
 Main.Shout("PFOFW", 0)
 Main.Shout("PFOFW", 6)
 Main.Shout("0APP", 12)
 Main.Shout("I4X", 17)
 Main.Shout("I4X", 21)
 Main.Shout("0APP", 25)

Обратите внимание, что на основе указанного выше набора невозможно создать последовательность длиной, например, 7. Вызов random_sequence(shouts, 7, shoutlimits, shouttranslate) приведет к ошибке.

Длины с плавающей запятой

Длины мотивов не обязательно должны быть целыми числами. При использовании мотивов с длиной с плавающей запятой рекомендуется указывать ненулевое значение δq для random_sequence. В следующем примере показано, как можно изменить структуру Shout с использованием длины с плавающей запятой.

struct FloatShout
  shout::String
  dur::Float64
  start::Float64
end

rs(x) = uppercase(randstring(x))

shouts = [FloatShout(rs(rand(3:5)), rand()+1, rand()) for k in 1:5]
shoutlimits(s::FloatShout) = (s.start, s.start + s.dur);
shouttranslate(s::FloatShout, n) = FloatShout(s.shout, s.dur, s.start + n);

q = 10.0
δq = 1.0

r, s = random_sequence(shouts, q, shoutlimits, shouttranslate, δq)

r
7-element Vector{Main.FloatShout}:
 Main.FloatShout("HIIY", 1.2271063471583912, 0.0)
 Main.FloatShout("HJA", 1.7413496261023735, 1.2271063471583914)
 Main.FloatShout("PNCNX", 1.2683820201529303, 2.968455973260765)
 Main.FloatShout("PNCNX", 1.2683820201529303, 4.236837993413696)
 Main.FloatShout("OMGH", 1.1938851898812177, 5.5052200135666265)
 Main.FloatShout("ONTJ", 1.8549771118240774, 6.699105203447845)
 Main.FloatShout("PNCNX", 1.2683820201529303, 8.554082315271922)
s
7-element Vector{Int64}:
 1
 3
 2
 2
 4
 5
 2