Being a musician myself, this recipe is one that is close to my heart. Imagine a group of musicians with a base theme in mind. But, they've never played with each other, and as the song changes, they must adapt to the core tones with their instruments and their styles. The emulation of this adaptation is implemented using an algorithm called harmony search.
We will need to define an objective function as a delegate in order to set it up before calling the function.
We will now implement the algorithm in a class:
HarmonySearch
class:using UnityEngine; using System.Collections; public class HarmonySearch : MonoBehaviour { }
[Range(1, 100)] public int memorySize = 30; public int pitchNum; // consolidation rate [Range(0.1f, 0.99f)] public float consRate = 0.9f; // adjustment rate [Range(0.1f, 0.99f)] public float adjsRate = 0.7f; public float range = 0.05f; public int numIterations; [Range(0.1f, 1.0f)] public float par = 0.3f;
Vector2
, so x
will represent the lowest bound and y the highest bound. The number of bounds must be equal to the number of pitches:public Vector2[] bounds;
private float[,] memory; private float[] solution; private float fitness; private float best;
private void Init() { memory = new float[memorySize, pitchNum]; solution = new float[memorySize]; fitness = ObjectiveFunction(memory); }
private float[] CreateHarmony() { float[] vector = new float[pitchNum]; int i; // next steps }
for (i = 0; i < pitchNum; i++) { // next steps }
if (Random.value < consRate) { int r = Random.Range(0, memory.Length); float val = memory[r, i]; if (Random.value < adjsRate) val = val + range * Random.Range(-1f, 1f); if (val < bounds[i].x) val = bounds[i].x; if (val > bounds[i].y) val = bounds[i].y; vector[i] = val; }
else { vector[i] = Random.Range(bounds[i].x, bounds[i].y); }
return vector;
public float[] Run() { // next steps }
Init(); int iterations = numIterations; float best = Mathf.Infinity;
while (iterations != 0) { iterations--; float[] harm = CreateHarmony(); fitness = ObjectiveFunction(harm); best = Mathf.Min(fitness, best); memory = harm; }
return