A Markov Chain might be a good fit for this problem.
A Markov chain is a stochastic process where the progression to the next state is determined by the current state. So for a given interval from your table you would apply weights to the "Leads to" values and then determine randomly to which state to progress.
I'd expect you to have less than 100 chords, therefore if you use 32 bits to represent probability series (likely extreme overkill) you'd end up with a 100x100x4 (40000) byte array for a flat Markov matrix representation. Depending on the sparsity of the matrix (e.g. if you have 50 chords, but each one typically maps to 2 or 3 chords) for speed and less importantly space reasons you may want an array of arrays where each final array element is (chord ID, probability).
In either case, one of the key points here is that you should use a probability series, not a probability sequence. That is, instead of saying "this chord has a 10% chance, and this one has a 10% chance, and this one has a 80% chance) say "the first chord has a 10% chance, the first two chords have a 20% chance, and the first three chords have a 100% chance."
Here's why: When you go to select a random but weighted value, you can generate a number in a fixed range (for unsigned integers, 0 to 0xFFFFFFFF) and then perform a binary search through the chords rather than linear search. (Search for the element with least probability series value that is still greater than or equal to the number you generated.)
On the other hand, if you've only got a few following chords for each chord, a linear search would likely be faster than a binary search due to a tighter loop, and then all the probability series saves you calculating a simple running sum of the probability values.
If you don't require the most staggeringly amazing performance (and I suspect you don't -- for a computer there's just not that many chords in a piece of music) for this portion of your code, I'd honestly just stick to a flat representation of a Markov matrix -- easy to understand, easy to implement, reasonable execution speed.
Just as a fun aside, this sort of thing lends itself well to thinking about predictive coding -- a common methodology in data compression. You might consider an n-gram based algorithm (e.g. PPM) to achieve higher-order structure in your music generation without too much example material required. It's been working in data compression for years.
It sounds like you want some form of directed, weighted graph where the nodes are the chords and the edges are the progression options with edge weights being the progression's likelihood.
发布评论
评论(3)
马尔可夫链可能很适合解决这个问题。
马尔可夫链是一个随机过程,其中下一个状态的进展由当前状态决定。因此,对于表中的给定间隔,您可以对“导致”值应用权重,然后随机确定要进展到哪个状态。
A Markov Chain might be a good fit for this problem.
A Markov chain is a stochastic process where the progression to the next state is determined by the current state. So for a given interval from your table you would apply weights to the "Leads to" values and then determine randomly to which state to progress.
我希望你的和弦少于 100 个,因此,如果你使用 32 位来表示概率系列(可能极端过度),你最终会得到一个 100x100x4 (40000) 字节数组作为平面马尔可夫矩阵表示。根据矩阵的稀疏性(例如,如果您有 50 个和弦,但每个和弦通常映射到 2 或 3 个和弦),为了速度和不太重要的空间原因,您可能需要一个数组数组,其中每个最终数组元素是(和弦 ID、可能性)。
无论哪种情况,这里的关键点之一是您应该使用概率序列,而不是概率序列。也就是说,不要说“这个和弦有 10% 的机会,这个和弦有 10% 的机会,这个和弦有 80% 的机会”,而是说“第一个和弦有 10% 的机会,前两个和弦有20% 的机会,前三个和弦有 100% 的机会。”
原因如下:当你去选择一个随机但加权的值时,你可以生成一个固定范围内的数字(对于无符号整数,0 到0xFFFFFFFF),然后通过和弦执行二分搜索而不是线性搜索(搜索概率系列值仍然大于或等于您生成的数字的元素。)
另一方面,如果您只进行搜索。对于每个和弦有几个后续和弦,由于循环更紧密,线性搜索可能比二分搜索更快,然后
如果不需要 ,所有概率级数都可以节省您计算概率值的简单运行总和。最令人惊叹的表演(我怀疑你不知道——对于计算机来说,一段音乐中没有那么多和弦)对于你的代码的这一部分,老实说,我只是坚持马尔可夫矩阵的平面表示——很容易理解、易于实施、执行速度合理。
顺便说一句,这种事情很适合思考预测编码——数据压缩中的一种常见方法。您可以考虑使用基于 n-gram 的算法(例如 PPM)来实现音乐生成中的高阶结构,而无需太多示例材料。它多年来一直致力于数据压缩。
I'd expect you to have less than 100 chords, therefore if you use 32 bits to represent probability series (likely extreme overkill) you'd end up with a 100x100x4 (40000) byte array for a flat Markov matrix representation. Depending on the sparsity of the matrix (e.g. if you have 50 chords, but each one typically maps to 2 or 3 chords) for speed and less importantly space reasons you may want an array of arrays where each final array element is (chord ID, probability).
In either case, one of the key points here is that you should use a probability series, not a probability sequence. That is, instead of saying "this chord has a 10% chance, and this one has a 10% chance, and this one has a 80% chance) say "the first chord has a 10% chance, the first two chords have a 20% chance, and the first three chords have a 100% chance."
Here's why: When you go to select a random but weighted value, you can generate a number in a fixed range (for unsigned integers, 0 to 0xFFFFFFFF) and then perform a binary search through the chords rather than linear search. (Search for the element with least probability series value that is still greater than or equal to the number you generated.)
On the other hand, if you've only got a few following chords for each chord, a linear search would likely be faster than a binary search due to a tighter loop, and then all the probability series saves you calculating a simple running sum of the probability values.
If you don't require the most staggeringly amazing performance (and I suspect you don't -- for a computer there's just not that many chords in a piece of music) for this portion of your code, I'd honestly just stick to a flat representation of a Markov matrix -- easy to understand, easy to implement, reasonable execution speed.
Just as a fun aside, this sort of thing lends itself well to thinking about predictive coding -- a common methodology in data compression. You might consider an n-gram based algorithm (e.g. PPM) to achieve higher-order structure in your music generation without too much example material required. It's been working in data compression for years.
听起来您想要某种形式的有向加权图,其中节点是和弦和边缘是进行选项,边缘权重是进行的可能性。
It sounds like you want some form of directed, weighted graph where the nodes are the chords and the edges are the progression options with edge weights being the progression's likelihood.