|
|
|
@ -2,7 +2,7 @@
|
|
|
|
|
"cells": [
|
|
|
|
|
{
|
|
|
|
|
"cell_type": "code",
|
|
|
|
|
"execution_count": 1,
|
|
|
|
|
"execution_count": 89,
|
|
|
|
|
"id": "806f6f69-1e0b-4d34-aac9-695c8531cdb1",
|
|
|
|
|
"metadata": {},
|
|
|
|
|
"outputs": [],
|
|
|
|
@ -79,7 +79,7 @@
|
|
|
|
|
"def edges(chords, min_symdiff, max_symdiff, max_chord_size): \n",
|
|
|
|
|
"\n",
|
|
|
|
|
" def reverse_movements(movements):\n",
|
|
|
|
|
" return {value['destination']:{'destination':key, 'cent_difference':value['cent_difference']} for key, value in movements.items()}\n",
|
|
|
|
|
" return {value['destination']:{'destination':key, 'cent_difference':value['cent_difference'] * -1} for key, value in movements.items()}\n",
|
|
|
|
|
"\n",
|
|
|
|
|
" def is_directly_tunable(intersection, diff):\n",
|
|
|
|
|
" # this only works for now when intersection if one element - need to fix that\n",
|
|
|
|
@ -166,7 +166,7 @@
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"cell_type": "code",
|
|
|
|
|
"execution_count": 2,
|
|
|
|
|
"execution_count": 214,
|
|
|
|
|
"id": "4e3ef738-7f64-47c3-9129-0450fd031375",
|
|
|
|
|
"metadata": {},
|
|
|
|
|
"outputs": [],
|
|
|
|
@ -180,17 +180,17 @@
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"cell_type": "code",
|
|
|
|
|
"execution_count": 7,
|
|
|
|
|
"execution_count": 215,
|
|
|
|
|
"id": "aea5215c-8551-4685-b761-11c2dc74cf22",
|
|
|
|
|
"metadata": {},
|
|
|
|
|
"outputs": [
|
|
|
|
|
{
|
|
|
|
|
"data": {
|
|
|
|
|
"text/plain": [
|
|
|
|
|
"144"
|
|
|
|
|
"260"
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
"execution_count": 7,
|
|
|
|
|
"execution_count": 215,
|
|
|
|
|
"metadata": {},
|
|
|
|
|
"output_type": "execute_result"
|
|
|
|
|
}
|
|
|
|
@ -198,6 +198,7 @@
|
|
|
|
|
"source": [
|
|
|
|
|
"from random import choice, choices\n",
|
|
|
|
|
"\n",
|
|
|
|
|
"# This is for the static version\n",
|
|
|
|
|
"def stochastic_hamiltonian(graph):\n",
|
|
|
|
|
" \n",
|
|
|
|
|
" def movement_size_weights(edges):\n",
|
|
|
|
@ -246,9 +247,11 @@
|
|
|
|
|
" for e in edges:\n",
|
|
|
|
|
" yield 10 if not has_voice_crossing(e) else 0\n",
|
|
|
|
|
"\n",
|
|
|
|
|
" def is_bass_rooted(chord):\n",
|
|
|
|
|
" return max([sum(abs(p) for p in collapse_pitch(pitch_difference(chord[0], p))) for p in chord[1:]]) == 1\n",
|
|
|
|
|
" \n",
|
|
|
|
|
" check_graph = graph.copy()\n",
|
|
|
|
|
" #next_node = choice(list(graph.nodes()))\n",
|
|
|
|
|
" next_node = list(graph.nodes())[0]\n",
|
|
|
|
|
" next_node = choice([node for node in graph.nodes() if is_bass_rooted(node)])\n",
|
|
|
|
|
" check_graph.remove_node(next_node)\n",
|
|
|
|
|
" for node in graph.nodes(data=True):\n",
|
|
|
|
|
" node[1]['count'] = 1\n",
|
|
|
|
@ -280,6 +283,30 @@
|
|
|
|
|
"len(path)"
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"cell_type": "code",
|
|
|
|
|
"execution_count": 25,
|
|
|
|
|
"id": "ac9e15be-5495-405c-9ce4-ae40d97c7814",
|
|
|
|
|
"metadata": {},
|
|
|
|
|
"outputs": [
|
|
|
|
|
{
|
|
|
|
|
"data": {
|
|
|
|
|
"text/plain": [
|
|
|
|
|
"[]"
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
"execution_count": 25,
|
|
|
|
|
"metadata": {},
|
|
|
|
|
"output_type": "execute_result"
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
"source": [
|
|
|
|
|
"def is_super_compact(chord):\n",
|
|
|
|
|
" return max([sum(abs(p) for p in collapse_pitch(pitch_difference(c[0], c[1]))) for c in combinations(chord, 2)]) == 1\n",
|
|
|
|
|
" \n",
|
|
|
|
|
"[node for node in graph.nodes() if is_super_compact(node)]"
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"cell_type": "code",
|
|
|
|
|
"execution_count": 11,
|
|
|
|
@ -372,6 +399,189 @@
|
|
|
|
|
"source": [
|
|
|
|
|
"lprun -f edge_data edges(chord_set, 3, 3, 4)"
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"cell_type": "code",
|
|
|
|
|
"execution_count": 180,
|
|
|
|
|
"id": "a76dc0f3-02e2-4739-9014-b53d3a590e3d",
|
|
|
|
|
"metadata": {},
|
|
|
|
|
"outputs": [],
|
|
|
|
|
"source": [
|
|
|
|
|
"dims = (2, 3, 5, 7, 11)\n",
|
|
|
|
|
"root = (0, 0, 0, 0, 0)\n",
|
|
|
|
|
"chord = (root,)\n",
|
|
|
|
|
"chord_set = chords(chord, root, 3, 3)\n",
|
|
|
|
|
"graph = generate_graph(chord_set, 2, 2, 3)"
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"cell_type": "code",
|
|
|
|
|
"execution_count": 213,
|
|
|
|
|
"id": "6e4ecb10-344b-4721-b2f4-68de91d712db",
|
|
|
|
|
"metadata": {},
|
|
|
|
|
"outputs": [
|
|
|
|
|
{
|
|
|
|
|
"name": "stdout",
|
|
|
|
|
"output_type": "stream",
|
|
|
|
|
"text": [
|
|
|
|
|
"((4, 0, 0, 0, -1), (3, 0, -1, 0, 0), (0, 0, 0, 0, 0))\n",
|
|
|
|
|
"0\n"
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"data": {
|
|
|
|
|
"text/plain": [
|
|
|
|
|
"144"
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
"execution_count": 213,
|
|
|
|
|
"metadata": {},
|
|
|
|
|
"output_type": "execute_result"
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
"source": [
|
|
|
|
|
"from random import choice, choices\n",
|
|
|
|
|
"\n",
|
|
|
|
|
"# This is for the rising version / yitgadal\n",
|
|
|
|
|
"def stochastic_hamiltonian(graph):\n",
|
|
|
|
|
" \n",
|
|
|
|
|
" def movement_size_weights(edges):\n",
|
|
|
|
|
" \n",
|
|
|
|
|
" def max_cent_diff(edge):\n",
|
|
|
|
|
" res = max([v for val in edge[2]['movements'].values() if (v:=val['cent_difference']) is not None])\n",
|
|
|
|
|
" return res\n",
|
|
|
|
|
" \n",
|
|
|
|
|
" def min_cent_diff(edge):\n",
|
|
|
|
|
" res = [v for val in edge[2]['movements'].values() if (v:=val['cent_difference']) is not None]\n",
|
|
|
|
|
" res.remove(0)\n",
|
|
|
|
|
" return min(res)\n",
|
|
|
|
|
" \n",
|
|
|
|
|
" for e in edges:\n",
|
|
|
|
|
" yield 1000 if ((max_cent_diff(e) < 175) and (min_cent_diff(e)) >= 0) else 1\n",
|
|
|
|
|
"\n",
|
|
|
|
|
" def hamiltonian_weights(edges):\n",
|
|
|
|
|
" for e in edges:\n",
|
|
|
|
|
" yield 10 if e[1] not in [path_edge[0] for path_edge in path] else 1 / graph.nodes[e[1]]['count']\n",
|
|
|
|
|
" \n",
|
|
|
|
|
" def contrary_motion_weights(edges):\n",
|
|
|
|
|
"\n",
|
|
|
|
|
" def is_contrary(edge):\n",
|
|
|
|
|
" cent_diffs = [v for val in edge[2]['movements'].values() if (v:=val['cent_difference']) is not None]\n",
|
|
|
|
|
" cent_diffs.sort()\n",
|
|
|
|
|
" return (cent_diffs[0] < 0) and (cent_diffs[1] == 0) and (cent_diffs[2] > 0)\n",
|
|
|
|
|
"\n",
|
|
|
|
|
" for e in edges:\n",
|
|
|
|
|
" yield 2 if is_contrary(e) else 1\n",
|
|
|
|
|
" \n",
|
|
|
|
|
" def is_directly_tunable_weights(edges):\n",
|
|
|
|
|
" for e in edges:\n",
|
|
|
|
|
" yield 10 if e[2]['is_directly_tunable'] else 0\n",
|
|
|
|
|
"\n",
|
|
|
|
|
" def transposition_weight(edges):\n",
|
|
|
|
|
" for e in edges:\n",
|
|
|
|
|
" yield 1000 if 0 <= hs_array_to_cents(e[2]['transposition']) < 100 else 0\n",
|
|
|
|
|
"\n",
|
|
|
|
|
" def is_sustained_voice(edges, voice):\n",
|
|
|
|
|
" \n",
|
|
|
|
|
" def is_sustained(edge):\n",
|
|
|
|
|
" source = list(edge[0])\n",
|
|
|
|
|
" ordered_source = sorted(source, key=hs_array_to_fr) \n",
|
|
|
|
|
" destination = [transpose_pitch(edge[2]['movements'][p]['destination'], edge[2]['transposition']) for p in source]\n",
|
|
|
|
|
" ordered_destination = sorted(destination, key=hs_array_to_fr)\n",
|
|
|
|
|
" return ordered_source[voice] == ordered_destination[voice]\n",
|
|
|
|
|
"\n",
|
|
|
|
|
" for e in edges:\n",
|
|
|
|
|
" yield 10 if is_sustained(e) else 0\n",
|
|
|
|
|
"\n",
|
|
|
|
|
" def voice_crossing_weights(edges):\n",
|
|
|
|
|
" \n",
|
|
|
|
|
" def has_voice_crossing(edge):\n",
|
|
|
|
|
" source = list(edge[0])\n",
|
|
|
|
|
" ordered_source = sorted(source, key=hs_array_to_fr) \n",
|
|
|
|
|
" source_order = [ordered_source.index(p) for p in source]\n",
|
|
|
|
|
" destination = [transpose_pitch(edge[2]['movements'][p]['destination'], edge[2]['transposition']) for p in source]\n",
|
|
|
|
|
" ordered_destination = sorted(destination, key=hs_array_to_fr)\n",
|
|
|
|
|
" destination_order = [ordered_destination.index(p) for p in destination]\n",
|
|
|
|
|
" return source_order != destination_order\n",
|
|
|
|
|
"\n",
|
|
|
|
|
" for e in edges:\n",
|
|
|
|
|
" yield 10 if not has_voice_crossing(e) else 0\n",
|
|
|
|
|
"\n",
|
|
|
|
|
" def is_bass_rooted(chord):\n",
|
|
|
|
|
" return max([sum(abs(p) for p in collapse_pitch(pitch_difference(chord[0], p))) for p in chord[1:]]) == 1\n",
|
|
|
|
|
" \n",
|
|
|
|
|
" check_graph = graph.copy()\n",
|
|
|
|
|
" #next_node = choice([node for node in graph.nodes() if is_bass_rooted(node)])\n",
|
|
|
|
|
" next_node = choice(list(graph.nodes()))\n",
|
|
|
|
|
" print(next_node)\n",
|
|
|
|
|
" check_graph.remove_node(next_node)\n",
|
|
|
|
|
" for node in graph.nodes(data=True):\n",
|
|
|
|
|
" node[1]['count'] = 1\n",
|
|
|
|
|
" path = []\n",
|
|
|
|
|
" while (nx.number_of_nodes(check_graph) > 0) and (len(path) < 500):\n",
|
|
|
|
|
" out_edges = list(graph.out_edges(next_node, data=True))\n",
|
|
|
|
|
" #print([l for l in zip(movement_size_weights(out_edges), hamiltonian_weights(out_edges))])\n",
|
|
|
|
|
" factors = [\n",
|
|
|
|
|
" movement_size_weights(out_edges), \n",
|
|
|
|
|
" hamiltonian_weights(out_edges), \n",
|
|
|
|
|
" #contrary_motion_weights(out_edges), \n",
|
|
|
|
|
" #is_directly_tunable_weights(out_edges),\n",
|
|
|
|
|
" voice_crossing_weights(out_edges),\n",
|
|
|
|
|
" #transposition_weight(out_edges)\n",
|
|
|
|
|
" #is_sustained_voice(out_edges, 0)\n",
|
|
|
|
|
" ]\n",
|
|
|
|
|
" weights = [prod(a) for a in zip(*factors)]\n",
|
|
|
|
|
" #print(weights)\n",
|
|
|
|
|
" edge = choices(out_edges, weights=weights)[0]\n",
|
|
|
|
|
" #print(edge)\n",
|
|
|
|
|
" #edge = random.choice(out_edges)\n",
|
|
|
|
|
" next_node = edge[1]\n",
|
|
|
|
|
" node[1]['count'] += 1\n",
|
|
|
|
|
" path.append(edge)\n",
|
|
|
|
|
" if next_node in check_graph.nodes:\n",
|
|
|
|
|
" check_graph.remove_node(next_node)\n",
|
|
|
|
|
" print(len(check_graph.nodes()))\n",
|
|
|
|
|
" return path\n",
|
|
|
|
|
" \n",
|
|
|
|
|
"path = stochastic_hamiltonian(graph)\n",
|
|
|
|
|
"#for edge in path:\n",
|
|
|
|
|
"# print(edge)\n",
|
|
|
|
|
"write_chord_sequence(path_to_chords(path, root))\n",
|
|
|
|
|
"len(path)"
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"cell_type": "code",
|
|
|
|
|
"execution_count": 212,
|
|
|
|
|
"id": "7b76d848-fe53-4b60-b414-46cfe570f78b",
|
|
|
|
|
"metadata": {},
|
|
|
|
|
"outputs": [
|
|
|
|
|
{
|
|
|
|
|
"name": "stdout",
|
|
|
|
|
"output_type": "stream",
|
|
|
|
|
"text": [
|
|
|
|
|
"((4, 0, 0, 0, -1), (2, -1, 0, 0, 0), (0, 0, 0, 0, 0))\n",
|
|
|
|
|
"0\n"
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"data": {
|
|
|
|
|
"text/plain": [
|
|
|
|
|
"219"
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
"execution_count": 212,
|
|
|
|
|
"metadata": {},
|
|
|
|
|
"output_type": "execute_result"
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
"source": [
|
|
|
|
|
"path = stochastic_hamiltonian(graph)\n",
|
|
|
|
|
"#for edge in path:\n",
|
|
|
|
|
"# print(edge)\n",
|
|
|
|
|
"write_chord_sequence(path_to_chords(path, root))\n",
|
|
|
|
|
"len(path)"
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
"metadata": {
|
|
|
|
|