Я работаю над цепью Маркова и создал двумерную хэш-карту, которая вычисляет взвешенные вероятности. Вывод этого работает отлично.
Я ищу, чтобы найти лучший способ вывести следующее значение. То, что у меня сейчас есть, не работает должным образом. Ent1.first
это входящий midiNote
, Ent2.first
является потенциальной исходящей стоимостью и Ent2.second
это взвешенная вероятность.
когда midiNote
приходит, мне нужно посмотреть в таблицу и найти взвешенные вероятности и используя rand()
выберите следующее значение. Одна проблема заключается в том, что мне нужно, чтобы это происходило только один раз, а не каждый раз в цикле for. Вот фрагмент расчета моей таблицы для простоты, но если вы хотите, чтобы я опубликовал весь код, дайте мне знать.
void getCountTable(int midiNote) {
for(auto const &ent1: cdf) {
midiNote = ent1.first;
for (auto const &ent2: ent1.second) {
//console out all resulting note transition weights
//std::cout << "Note: " << ent1.first << std::endl <<"Next note: " << ent2.first <<std::endl << "Weight: " << ent2.second << std::endl << std::endl;
//TRYING TO FIGURE HOW TO HANDLE THIS. JUST WANT TO HAPPEN ONCE FOR EACH INCOMING VALUE
//psuedo-random values between 0-1
float r = static_cast <float> (rand()) / static_cast<float> (RAND_MAX);
//calculate next value
if (r < ent2.second) {
int output = ent2.first;
std::cout << ent1.first << " " << output << std::endl;
}
}
}
}
В настоящее время вы каждый раз создаете новое случайное число в вашем внутреннем цикле и сравниваете его с вероятностью такой возможности. Это будет означать, что иногда один элемент будет соответствовать (хорошо), но иногда вы получите ноль или два или более элементов, совпадающих (это случайно).
Один из способов выбрать только одну возможность из всех вариантов — это сгенерировать одно случайное число, а затем перебирать возможности до тех пор, пока сумма всех возможностей пока не станет больше, чем сгенерированное вами случайное число.
Изменение порядка кода (не проверено)
midiNote = ent1.first;
//psuedo-random values between 0-1
float r = static_cast <float> (rand()) / static_cast<float> (RAND_MAX);
float sum = 0;
int output = 0;
for (auto const &ent2: ent1.second){
sum += ent2.second;
if (sum >= r) {
output = ent2.first;
std::cout << ent1.first << " " << output << std::endl;
break;
}
}
Это должно сработать, хотя, учитывая неточность дополнений с плавающей запятой, может стоить дефолт output
до последнего пункта ent1.second
если ничего не найдено (например, это может произойти, если sum
заканчивается на 0,999, но r
было 0,9999)
Я обнаружил, что должно быть сравнение между картой и входящим значением midi. Также изменены вероятности для первой записи на второй карте и результирующего вывода в качестве второй записи. Модифицированы некоторые и предоставлены все ниже.
void nextNote(int midiNote){
float r = static_cast <float> (rand()) / static_cast<float> (RAND_MAX);
int output = 0;
float sum = 0;
for (auto const & ent1: cdf){
if(ent1.first == midiNote){
for (auto const & ent2: ent1.second){
sum+= ent2.first;
std::cout <<sum << std::endl;
if(sum >= r){
output = ent2.second;
std::cout << output <<std::endl;
break;
}
}
}
}}