Выбор элементов из списка с помощью взвешенных вероятностей - PullRequest
0 голосов
/ 12 декабря 2018

У меня есть следующий список:

60, 62, 63, 65, 66, 68, 69, 71, 73, 74, 76, 77, 79, 80, 82, 83, 85, 87, 88

, и мне нужно выбрать высоты из списка с этими условиями:

  1. 100 шагов должны быть выбраны

  2. Сначала необходимо выбрать случайный шаг из списка, а следующие высоты, выбранные из списка, будут определены с помощью взвешенных вероятностей.

Что я пытаюсь сделать, так это то, что после того, как первый шаг случайным образом выбран из списка (71), следующий выбранный шаг будет определяться взвешенной вероятностью в соответствии с его близостью к 71 (69 и 73 имели бы наибольшую вероятность того, чтовыбрано, за ним следуют 68 и 74 и т. д.)

Предположим, что 68 будет выбран в качестве шага, следующего за 71, тогда следующий шаг, следующий за 68, будет определяться взвешенной вероятностью в соответствии с его близостью к 68 (66 и 69будет иметь наибольшую вероятность выбора, а затем 65 и 71, и т. д.)

Моя главная проблема заключается в том, что, хотя программа работает безно при наличии ошибок (то есть, по крайней мере, сообщение об ошибке не прерывает его выполнение), я все еще не уверен, работает ли он так, как я планировал.Я говорю об этом потому, что, хотя я хочу, чтобы программа выбирала 100 нот, она всегда выбирает ровно 5050 нот.Почему 5050?

Вот мой код:

from music import *
from random import *

solo = Phrase()
solo.setTempo(100)

durations = []
pitches = []
pitchIndex = ()
numberOfNotesInSolo = 0
listOfAvailablePitches = [60, 62, 63, 65, 66, 68, 69, 71, 73, 74, 76, 77, 79, 80, 82, 83, 85, 87, 88]

pitch = choice(listOfAvailablePitches)
pitchIndex = listOfAvailablePitches.index(pitch)

while numberOfNotesInSolo < 100:

   weightedProbabilitiesForPitches = [pitchIndex + 1] * 20 + [pitchIndex - 1] * 20 + [pitchIndex + 2] * 15 + [pitchIndex - 2] * 15 + [pitchIndex + 3] * 12 + [pitchIndex - 3] * 12 + [pitchIndex + 4] * 8 + [pitchIndex - 4] * 8 + [pitchIndex + 5] * 5 + [pitchIndex - 5] * 5 + [pitchIndex + 6] * 3 + [pitchIndex - 6] * 3        

   pitchIndex = choice(weightedProbabilitiesForPitches)         

   while pitchIndex > 18 or pitchIndex < 0:

      pitchIndex = choice(weightedProbabilitiesForPitches)

   pitch = listOfAvailablePitches[pitchIndex]
   weightedProbabilitiesForDurations = [SN] * 1 + [EN] * 1 + [DEN] * 1 + [QN] * 1 + [DQN] * 1

   duration = choice(weightedProbabilitiesForDurations)
   pitches.append(pitch)
   durations.append(duration)
   solo.addNoteList(pitches, durations)
   numberOfNotesInSolo = numberOfNotesInSolo + 1     

print solo

1 Ответ

0 голосов
/ 15 декабря 2018

Я думаю, что проблема, с которой вы сталкиваетесь, заключается в том, как создать список веса для вашего списка высот.Вот мой код:

pitches =  [60, 62, 63, 65, 66, 68, 69, 71, 73, 74, 76, 77, 79, 80, 82, 83, 85, 87, 88]
num = len(pitches)
choice = random.randint(0, num-1)
below = choice
above = num-choice-1
weightbelow = list(range(num-1, num-1-below, -1))[::-1]
weightabove = list(range(num-1, num-1-above, -1))
weight = weightbelow + [num] + weightabove

Например, если choice шага составляет 11 (то есть pitches[11]=77), вес станет:

[8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 18, 17, 16, 15, 14, 13, 12]

Затем вы можете сделать взвешенный случайный выбор, такой как в Взвешенная версия random.choice

Приведенный выше код должен создать возрастающий список целых чисел до len(pitches)-1, затем нисходящийсоставьте список подходящей длины по вашему выбору, затем объедините их вместе.Если вам нужен другой дистрибутив, отличный от линейного, выполните его преобразование.

...