<p><div><div><div><div data-width="100" data-show-faces="false" data-send="true" data-layout="button_count" data-height="21" data-href="https://www.r-bloggers.com/genetic-music-from-schoenberg-to-bach/"></div></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="https://fronkonstin.com/2017/04/27/genetic-music-from-schoenberg-to-bach/"> R – Fronkonstin</a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<div class="twitter-share"><a target="_blank" class="twitter-share-button" rel="nofollow" href="https://twitter.com/intent/tweet?url=https%3A%2F%2Ffronkonstin.com%2F2017%2F04%2F27%2Fgenetic-music-from-schoenberg-to-bach%2F&via=aschinchon">Tweet</a></div>
<blockquote><p>Bach, the epitome of a musician who strove all life long and finally acquired the ‘Habit of Perfection’, was a thoroughly imperfect human being (John Eliot Gardiner, Bach: Music in the Castle of Heaven)</p>
</blockquote>
<p>Sometimes I dream awake and imagine I am a famous musician.  I fantasize being Paco de Lucía playing <a target="_blank" rel="nofollow" href="https://www.youtube.com/watch?v=m5WA_JxN_fs">Mi niño Curro</a> alone on the stage, Thom Yorke singing <a target="_blank" rel="nofollow" href="https://www.youtube.com/watch?v=HDS4wOd_o1I">Fake plastic trees</a> at Glastombury or Noel Gallagher singing <a target="_blank" rel="nofollow" href="https://www.youtube.com/watch?v=jBbyc3t-Ctc">Don’t look back in anger</a> for a devoted crowd.</p>
<p>My parents gave me the opportunity to learn music, and this has been one of the best gifts I have received ever. I played the cello intensively until I had children but I still have enough skills to play some pieces. One of that is the Prelude of Suite No. 1 of J. S. Bach. It is very close to the limit of my possibilities but I love it. It is timeless, thrilling, provocative and elegant: an absolute masterpiece. I also imagine myself often playing it as well as my admired Yo-Yo Ma <a target="_blank" rel="nofollow" href="https://www.youtube.com/watch?v=PCicM6i59_I">does</a>.</p>
<p>The aim of this experiment is to <em>discern</em> first 4 beats of the prelude using a genetic algorithm. First of all, let’s listen our goal melody, created with tuneR package (sorry for the sound, Mr. Bach):</p>
<p><br>
<audio controls="controls" preload="none" class="wp-audio-shortcode"><source src="https://fronkonstin.com/wp-content/uploads/2017/04/PreludeSample.wav?_=1" type="audio/wav"><a target="_blank" rel="nofollow" href="https://fronkonstin.com/wp-content/uploads/2017/04/PreludeSample.wav">https://fronkonstin.com/wp-content/uploads/2017/04/PreludeSample.wav</a></audio></p>
<p>The <a target="_blank" rel="nofollow" href="http://www.tnt-audio.com/topics/frequency_e.html">frequency range</a> of cello goes from 65.41 Hz to 987.77 Hz. Using the <a target="_blank" rel="nofollow" href="http://www.phy.mtu.edu/~suits/NoteFreqCalcs.html">basic formula for the frequency</a> of the notes, it means that a cello can produce 48 different notes. I generated the next codification for the 48 notes of the cello:</p>
<table>
<thead>
<tr>
<th>frequency (hz)</th>
<th>note</th>
<th>code</th>
</tr>
</thead>
<tbody>
<tr>
<td>65.41</td>
<td>C2</td>
<td>a</td>
</tr>
<tr>
<td>69.30</td>
<td>C#2/Db2</td>
<td>b</td>
</tr>
<tr>
<td>73.42</td>
<td>D2</td>
<td>c</td>
</tr>
<tr>
<td>77.78</td>
<td>D#2/Eb2</td>
<td>d</td>
</tr>
<tr>
<td>82.41</td>
<td>E2</td>
<td>e</td>
</tr>
<tr>
<td>87.31</td>
<td>F2</td>
<td>f</td>
</tr>
<tr>
<td>92.50</td>
<td>F#2/Gb2</td>
<td>g</td>
</tr>
<tr>
<td>98.00</td>
<td>G2</td>
<td>h</td>
</tr>
<tr>
<td>103.83</td>
<td>G#2/Ab2</td>
<td>i</td>
</tr>
<tr>
<td>110.00</td>
<td>A2</td>
<td>j</td>
</tr>
<tr>
<td>116.54</td>
<td>A#2/Bb2</td>
<td>k</td>
</tr>
<tr>
<td>123.47</td>
<td>B2</td>
<td>l</td>
</tr>
<tr>
<td>130.81</td>
<td>C3</td>
<td>m</td>
</tr>
<tr>
<td>138.59</td>
<td>C#3/Db3</td>
<td>n</td>
</tr>
<tr>
<td>146.83</td>
<td>D3</td>
<td>o</td>
</tr>
<tr>
<td>155.56</td>
<td>D#3/Eb3</td>
<td>p</td>
</tr>
<tr>
<td>164.81</td>
<td>E3</td>
<td>q</td>
</tr>
<tr>
<td>174.61</td>
<td>F3</td>
<td>r</td>
</tr>
<tr>
<td>185.00</td>
<td>F#3/Gb3</td>
<td>s</td>
</tr>
<tr>
<td>196.00</td>
<td>G3</td>
<td>t</td>
</tr>
<tr>
<td>207.65</td>
<td>G#3/Ab3</td>
<td>u</td>
</tr>
<tr>
<td>220.00</td>
<td>A3</td>
<td>v</td>
</tr>
<tr>
<td>233.08</td>
<td>A#3/Bb3</td>
<td>w</td>
</tr>
<tr>
<td>246.94</td>
<td>B3</td>
<td>x</td>
</tr>
<tr>
<td>261.63</td>
<td>C4</td>
<td>y</td>
</tr>
<tr>
<td>277.18</td>
<td>C#4/Db4</td>
<td>z</td>
</tr>
<tr>
<td>293.66</td>
<td>D4</td>
<td>A</td>
</tr>
<tr>
<td>311.13</td>
<td>D#4/Eb4</td>
<td>B</td>
</tr>
<tr>
<td>329.63</td>
<td>E4</td>
<td>C</td>
</tr>
<tr>
<td>349.23</td>
<td>F4</td>
<td>D</td>
</tr>
<tr>
<td>369.99</td>
<td>F#4/Gb4</td>
<td>E</td>
</tr>
<tr>
<td>392.00</td>
<td>G4</td>
<td>F</td>
</tr>
<tr>
<td>415.30</td>
<td>G#4/Ab4</td>
<td>G</td>
</tr>
<tr>
<td>440.00</td>
<td>A4</td>
<td>H</td>
</tr>
<tr>
<td>466.16</td>
<td>A#4/Bb4</td>
<td>I</td>
</tr>
<tr>
<td>493.88</td>
<td>B4</td>
<td>J</td>
</tr>
<tr>
<td>523.25</td>
<td>C5</td>
<td>K</td>
</tr>
<tr>
<td>554.37</td>
<td>C#5/Db5</td>
<td>L</td>
</tr>
<tr>
<td>587.33</td>
<td>D5</td>
<td>M</td>
</tr>
<tr>
<td>622.25</td>
<td>D#5/Eb5</td>
<td>N</td>
</tr>
<tr>
<td>659.26</td>
<td>E5</td>
<td>O</td>
</tr>
<tr>
<td>698.46</td>
<td>F5</td>
<td>P</td>
</tr>
<tr>
<td>739.99</td>
<td>F#5/Gb5</td>
<td>Q</td>
</tr>
<tr>
<td>783.99</td>
<td>G5</td>
<td>R</td>
</tr>
<tr>
<td>830.61</td>
<td>G#5/Ab5</td>
<td>S</td>
</tr>
<tr>
<td>880.00</td>
<td>A5</td>
<td>T</td>
</tr>
<tr>
<td>932.33</td>
<td>A#5/Bb5</td>
<td>U</td>
</tr>
<tr>
<td>987.77</td>
<td>B5</td>
<td>V</td>
</tr>
</tbody>
</table>
<p>So our <em>goal</em> melody is codified like this:</p>
<p>tAJHJAJAtAJHJAJAtCKJKCKCtCKJKCKCtEKJKEKEtEKJKEKEtFJHJFJFtFJHJFJF</p>
<p>I start with a population of 500 random melodies. All of them have 64 notes, the same length as the goal melody has. Given a melody, the algorithm compares it with the goal melody to calculate its fitness, with the following formula:</p>
<p><img title="fitness= {2}^{\displaystyle number of correct notes}" alt="fitness= {2}^{\displaystyle number of correct notes}" class="latex" src="https://s0.wp.com/latex.php?latex=fitness%3D+%7B2%7D%5E%7B%5Cdisplaystyle+number+of+correct+notes%7D&bg=ffffff&%23038;fg=000&%23038;s=0"></p>
<p>For example, a melody with 5 correct notes has a fitness of 32. <em>Being correct</em> means being the right note in the right place. After measuring fitness of all melodies, I select 250 couples of individuals depending of its fitness (the more fitness, the more probability of being selected). Each couple generates two children for the next generation depending on certain probability, called crossover rate. Crossing operation is not always applied. Once two parents are selected, a random crossover point is chosen. At that point in both strings the genetic material from the left side of one parent is spliced to the material from the right side of other parent. The next figure illustrates the idea:</p>
<p><img sizes="(max-width: 604px) 100vw, 604px" data-image-description="" data-orig-file="https://i0.wp.com/fronkonstin.com/wp-content/uploads/2017/04/genetic1.png?fit=1685%2C327&amp;ssl=1" data-orig-size="1685,327" data-image-title="genetic1" class="wp-image-4061" data-comments-opened="1" data-recalc-dims="1" data-attachment-id="4061" data-permalink="https://fronkonstin.com/2017/04/27/genetic-music-from-schoenberg-to-bach/genetic1/" alt="" data-medium-file="https://i0.wp.com/fronkonstin.com/wp-content/uploads/2017/04/genetic1.png?fit=300%2C58&amp;ssl=1" data-large-file="https://i0.wp.com/fronkonstin.com/wp-content/uploads/2017/04/genetic1.png?fit=604%2C117&amp;ssl=1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" src="https://i0.wp.com/fronkonstin.com/wp-content/uploads/2017/04/genetic1.png?resize=604%2C117&ssl=1"></p>
<p>So two parents give birth to two children for the next generation. The last thing to do is mutate children. Once again, mutation is not always applied since it depends on a rate, usually small. Mutation introduces some new notes (new genetic material) to the next population. It increases convergence speed and reduces the probability to obtain a local optimum.</p>
<p>How many 32 -length melodies can be written with 48 notes? The answer is 48<sup>32</sup>, which is this extremely big number:</p>
<p>630.550.095.814.788.844.406.620.626.462.420.008.802.064.662.402.084.486</p>
<p>To understand how enormous is, let’s suppose we could work with <a target="_blank" rel="nofollow" href="https://en.wikipedia.org/wiki/Sunway_TaihuLight">Sunway TaihuLight</a>, the fastest supercomputer in the world nowadays. This <em>monster</em> can do 93.000.000.000.000.000 floating-point operations per second so it will expend more than 214.995.831.974.513.789.322.026.202.008 years to calculate the fitness of all possible melodies: brute force is not an option.</p>
<p>A genetic algorithm does the job in just a few iterations. Best melodies introduce <em>innovations</em> which increase the average fitness of the whole population as well as its maximum fitness. Next table shows the evolution of an execution of the algorithm for a crossover rate equal of 75% and a mutation  rate of 1% (not exhaustive):</p>
<table>
<thead>
<tr>
<th>iteration</th>
<th>best melody</th>
<th>correct notes</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>OStxSTSbHwdsJAfTcRpoiNTRtRUxKhuRuKMcVNcBjRJNhENrVeFsPiegUpJHvRHw</td>
<td>7</td>
</tr>
<tr>
<td>5</td>
<td>tdbxSTSbHwdsJAfTcRpoiNTRtRITopoCPORzDdiFkEKrhEKtMHytiffzttJHvRHw</td>
<td>12</td>
</tr>
<tr>
<td>20</td>
<td>tAGHwdtUHzdMJATVACjJKVnetRQxKCKCtBKjqwiFkEKKhEKEMHyQiFfztUJHlRHF</td>
<td>25</td>
</tr>
<tr>
<td>35</td>
<td>tAGHwAQUjAdsJAGAcUjJKCLCtRQxKCKCtEKAqwKEzEKJhEKEMHytIFfFtUJHJRHF</td>
<td>35</td>
</tr>
<tr>
<td>50</td>
<td>tAJHwAJGjAJHJAJAtUCJKCkCtRUxKCKCtEKJKwKEtEKyhEKEMHyHrFfFtUJHJFHF</td>
<td>45</td>
</tr>
<tr>
<td>65</td>
<td>tAJHJAJGjAJHJAJAtUKJKCLCtCKxKCKCtEKJKwKEtEKyhEKEMHJHNFJFtFJHJFOF</td>
<td>52</td>
</tr>
<tr>
<td>80</td>
<td>tAJHJAJmtAJHJAJAtUKJKCLCtCKJKCKCtEKJKEKEtEKyMEKEMHJHJFJFtFJHJFOF</td>
<td>56</td>
</tr>
<tr>
<td>95</td>
<td>tAJHJAJjtAJHJAJAtUKJKCLCtCKJKCKCtEKJKEKEtEKJhEKEtFJHJFJFtFJHJFRF</td>
<td>59</td>
</tr>
<tr>
<td>110</td>
<td>tAJHJAJktAJHJAJAtUKJKCvCtCKJKCKCtEKJKEKEtEKJKEKEtFJHJFJFtFJHJFJF</td>
<td>61</td>
</tr>
<tr>
<td>125</td>
<td>tAJHJAJAtAJHJAJAtCKJKCKCtCKJKCKCtEKJKEKEtEKJKEKEtFJHJFJFtFJHJFJF</td>
<td>64</td>
</tr>
</tbody>
</table>
<p>The optimum is reached in just 125 iterations. It is funny to merge the best melodies of some iterations. This sample blends four of them. The first one comes from the first initial population (the <em>Schoenberg flavored</em>) and the last one is our goal melody.  The other two were randomly picked from the rest iterations. It is nice to hear how the genetic algorithm turns randomness into the wonderful Bach’s melody:</p>
<p><audio controls="controls" preload="none" class="wp-audio-shortcode"><source src="https://fronkonstin.com/wp-content/uploads/2017/04/Composition.wav?_=2" type="audio/wav"><a target="_blank" rel="nofollow" href="https://fronkonstin.com/wp-content/uploads/2017/04/Composition.wav">https://fronkonstin.com/wp-content/uploads/2017/04/Composition.wav</a></audio></p>
<p>This experiment was inspired by <a target="_blank" rel="nofollow" href="https://mitpress.mit.edu/books/computational-beauty-nature">The Computational Beauty of Nature</a>, a splendid book by Gary William Flake I strongly recommend you.</p>
<p>This is the code of the experiment:</p>
<pre>
library(tuneR)
library(stringdist)
library(dplyr)
#Function to calculate frequency
freq=function(n) 440*(2^(1/12))^n
#cello notes
notes=c(&quot;C2&quot;,
        &quot;C#2/Db2&quot;,
        &quot;D2&quot;,
        &quot;D#2/Eb2&quot;,
        &quot;E2&quot;,
        &quot;F2&quot;,
        &quot;F#2/Gb2&quot;,
        &quot;G2&quot;,
        &quot;G#2/Ab2&quot;,
        &quot;A2&quot;,
        &quot;A#2/Bb2&quot;,
        &quot;B2&quot;,
        &quot;C3&quot;,
        &quot;C#3/Db3&quot;,
        &quot;D3&quot;,
        &quot;D#3/Eb3&quot;,
        &quot;E3&quot;,
        &quot;F3&quot;,
        &quot;F#3/Gb3&quot;,
        &quot;G3&quot;,
        &quot;G#3/Ab3&quot;,
        &quot;A3&quot;,
        &quot;A#3/Bb3&quot;,
        &quot;B3&quot;,
        &quot;C4&quot;,
        &quot;C#4/Db4&quot;,
        &quot;D4&quot;,
        &quot;D#4/Eb4&quot;,
        &quot;E4&quot;,
        &quot;F4&quot;,
        &quot;F#4/Gb4&quot;,
        &quot;G4&quot;,
        &quot;G#4/Ab4&quot;,
        &quot;A4&quot;,
        &quot;A#4/Bb4&quot;,
        &quot;B4&quot;,
        &quot;C5&quot;,
        &quot;C#5/Db5&quot;,
        &quot;D5&quot;,
        &quot;D#5/Eb5&quot;,
        &quot;E5&quot;,
        &quot;F5&quot;,
        &quot;F#5/Gb5&quot;,
        &quot;G5&quot;,
        &quot;G#5/Ab5&quot;,
        &quot;A5&quot;,
        &quot;A#5/Bb5&quot;,
        &quot;B5&quot;)
#Table of frequencies
frequencies=data.frame(n=-33:14) %>% 
  mutate(frequency=round(freq(n),4),
         note=notes,
         code=c(letters, toupper(letters))[1:48])
#Codification of the goal melody
prelude=&quot;tAJHJAJAtAJHJAJAtCKJKCKCtCKJKCKCtEKJKEKEtEKJKEKEtFJHJFJFtFJHJFJF&quot;
#Sample wav
if (exists(&quot;all_wave&quot;)) rm(all_wave)
frequencies %>% 
  filter(code==substr(prelude,1,1)) %>% 
  select(frequency) %>% 
  as.numeric %>% 
  sine(duration = 10000)->all_wave
for (i in 2:nchar(prelude)) 
  frequencies %>% 
  filter(code==substr(prelude,i,i)) %>% 
  select(frequency) %>% 
  as.numeric %>% 
  sine(duration = 10000) %>% bind(all_wave, .)->all_wave  
play(all_wave)
writeWave(all_wave, 'PreludeSample.wav')

popsize=500 #Population size
length=nchar(prelude)
genes=frequencies$code
maxfitness=2^(1-(stringdist(prelude, prelude, method=&quot;hamming&quot;)-length))
maxiter=200 #Max number of iterations
iter=1
mutrate=0.01
#Initial population
replicate(popsize, sample(genes, length, replace = TRUE)) %>%
  apply(2, function(x) paste(x,collapse=&quot;&quot;)) -> population
#Fitness evaluation
fitness=sapply(population, function(x) 2^(1-(stringdist(x, prelude, method=&quot;hamming&quot;)-length)), USE.NAMES=FALSE)
#Maximum fitness
maxfitenss_iter=max(fitness)
#Best melody
which((fitness)==max(fitness)) %>% min %>% population[.] ->bestfit
results=data.frame(iteration=iter, best_melody=bestfit, correct_notes=log(maxfitenss_iter, base = 2)-1)
#Execution of the algorithm
while(maxfitenss_iter&lt;maxfitness &amp; iter&lt;maxiter)
{
  population2=c()
  for (i in 1:(popsize/2))
  {
    parents=sample(1:popsize, size=2, prob=fitness/sum(fitness), replace=FALSE) 
    mix=sample(1:(length-1), 1)
    
    if (runif(1)>.25)
    {
      p1=paste0(substr(population[parents[1]],1,mix), substr(population[parents[2]],mix+1,length))
      p2=paste0(substr(population[parents[2]],1,mix), substr(population[parents[1]],mix+1,length))
    }
    else
    {
      p1=population[parents[1]]
      p2=population[parents[2]]
    }
    for (j in 1:length) if(runif(1)&lt;mutrate) substr(p1,j,j)=sample(genes,1)
    for (j in 1:length) if(runif(1)&lt;mutrate) substr(p2,j,j)=sample(genes,1)
    c(p1, p2) %>% c(population2)->population2
  }
  #New population
  population=population2
  fitness=sapply(population, function(x) 2^(1-(stringdist(x, prelude, method=&quot;hamming&quot;)-length)), USE.NAMES=FALSE)
  which((fitness)==max(fitness)) %>% min %>% population[.] ->bestfit
  print(paste0(&quot;Iteration &quot;,iter, &quot;: &quot;, bestfit))
  maxfitenss_iter=max(fitness)
  iter=iter+1
  data.frame(iteration=iter, best_melody=bestfit, correct_notes=log(maxfitenss_iter, base = 2)-1) %>% rbind(results) -> results
}
</pre>
<p>
<div>
<div>To <strong>leave a comment</strong> for the author, please follow the link and comment on their blog: <strong><a href="https://fronkonstin.com/2017/04/27/genetic-music-from-schoenberg-to-bach/"> R – Fronkonstin</a></strong>.</div>
<hr>
<a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers.com</a> offers <strong><a rel="nofollow" href="https://feedburner.google.com/fb/a/mailverify?uri=RBloggers">daily e-mail updates</a></strong> about <a title="The R Project for Statistical Computing" rel="nofollow" href="https://www.r-project.org/">R</a> news and <a title="R tutorials" rel="nofollow" href="https://www.r-bloggers.com/search/tutorial">tutorials</a> on topics such as: <a title="Data science" rel="nofollow" href="https://www.r-bloggers.com/search/data%20science">Data science</a>, <a title="Big Data" rel="nofollow" href="https://www.r-bloggers.com/search/Big%20Data">Big Data, <a title="R jobs" rel="nofollow" href="https://www.r-users.com/">R jobs</a>, visualization (<a title="ggplot and ggplot2 tutorials" rel="nofollow" href="https://www.r-bloggers.com/search/ggplot2">ggplot2</a>, <a title="Boxplots using lattice and ggplot2 tutorials" rel="nofollow" href="https://www.r-bloggers.com/search/boxplot">Boxplots</a>, <a title="Maps and gis" rel="nofollow" href="https://www.r-bloggers.com/search/map">maps</a>, <a title="Animation in R" rel="nofollow" href="https://www.r-bloggers.com/search/animation">animation</a>), programming (<a title="RStudio IDE for R" rel="nofollow" href="https://www.r-bloggers.com/search/RStudio">RStudio</a>, <a title="Sweave and literate programming" rel="nofollow" href="https://www.r-bloggers.com/search/sweave">Sweave</a>, <a title="LaTeX in R" rel="nofollow" href="https://www.r-bloggers.com/search/LaTeX">LaTeX</a>, <a title="SQL and databases" rel="nofollow" href="https://www.r-bloggers.com/search/SQL">SQL</a>, <a title="Eclipse IDE for R" rel="nofollow" href="https://www.r-bloggers.com/search/eclipse">Eclipse</a>, <a title="git and github, Version Control System" rel="nofollow" href="https://www.r-bloggers.com/search/git">git</a>, <a title="Large data in R using Hadoop" rel="nofollow" href="https://www.r-bloggers.com/search/hadoop">hadoop</a>, <a title="Web Scraping of google, facebook, yahoo, twitter and more using R" rel="nofollow" href="https://www.r-bloggers.com/search/Web+Scraping">Web Scraping</a>) statistics (<a title="Regressions and ANOVA analysis tutorials" rel="nofollow" href="https://www.r-bloggers.com/search/regression">regression</a>, <a title="principal component analysis tutorial" rel="nofollow" href="https://www.r-bloggers.com/search/PCA">PCA</a>, <a title="Time series" rel="nofollow" href="https://www.r-bloggers.com/search/time+series">time series</a>, <a title="finance trading" rel="nofollow" href="https://www.r-bloggers.com/search/trading">trading</a>) and more...
<img height="1" alt="" width="1" src="http://feeds.feedburner.com/~r/RBloggers/~4/Af5l2eP5BfA"></a></div>