DISEÑO E IMPLEMENTACIÓN DE UN SISTEMA DE RESTRICCIONES DE ARMONÍA MUSICAL PARA MOZART JESSICA LILIÁN RODRÍGUEZ Escuela de Ingeniería de Sistemas y Computación Facultad de Ingeniería Universidad del Valle Cali Colombia DISEÑO E IMPLEMENTACIÓN DE UN SISTEMA DE RESTRICCIONES DE ARMONÍA MUSICAL PARA MOZART JESSICA LILIÁN RODRÍGUEZ Trabajo presentado para optar al título de Ingeniera de Sistemas Escuela de Ingeniería de Sistemas y Computación Facultad de Ingeniería Universidad del Valle Cali Colombia A mi papá que es mi motor, mi fortaleza, mi fé, el forjador de mi carácter y el responsable de mis logros. RESUMEN La composición asistida por computador es un área muy interesante en el mundo de las ciencias de la computación que ha sido atacada desde diversos campos de la Inteligencia Artificial, entre ellos, la programación por restricciones. Esta permite resolver problemas musicales combinatorios de una forma óptima y natural, ya que la música está formada de múltiples características que caen sobre sus estructuras internas y que pueden ser vistas como un conjunto de restricciones sobre variables de dominios finitos (notas). A pesar de la relación entre las restricciones y las reglas musicales, y de las investigaciones sobre composición de melodías por medio del paradigma de las restricciones, en el entorno de programación Mozart1 no existe un conjunto definido de estructuras musicales, ni un conjunto de restricciones o propagadores que aprovechen las ventajas de Oz para atacar directamente problemas de satisfacción de restricciones musicales sin invertir tiempo en la abstracción del modelo a dominios finitos. Este proyecto presenta a MuZa, un sistema pequeño de estructuras y restricciones musicales de armonía para Mozart, que permite manipular estructuras musicales y relaciones sobre sus dominios de una forma más natural en cuanto a teoría musical, dejando las abstracciones a dominios finitos de modo transparente para el usuario. A lo largo del documento se exponen las características implementadas en MuZa, como producto de una labor investigativa sobre modelos de estructuras musicales y armonía. Se espera que la investigación realizada junto con el desarrollo del sistema de restricciones, sirvan como invitación a quienes deseen continuar la labor en esta área, dado que este trabajo sólo representa un comienzo, y una puerta abierta para futuros desarrollos de más librerías, propagadores, estructuras musicales, tipos de restricciones e interfaces visuales amigables para los compositores, de modo que en algún momento pueda desarrollarse una herramienta de composición musical completa y fácil de usar. En adelante, el término Mozart hará referencia al entorno de programación para Oz, a menos que se indique lo contrario. 1 Contenido INTRODUCCIÓN ............................................................................................................... 1 I OBJETIVOS, PLANTEAMIENTO Y JUSTIFICACIÓN......................................... 2 1 OBJETIVOS......................................................................................................................... 2 1.1 1.2 OBJETIVO GENERAL............................................................................................................. 2 OBJETIVOS ESPECÍFICOS..................................................................................................... 2 2 FORMULACIÓN DEL PROBLEMA .............................................................................. 3 3 JUSTIFICACIÓN................................................................................................................ 3 II MARCO DE REFERENCIA ....................................................................................... 6 4 ESTADO DEL ARTE ......................................................................................................... 6 4.1 4.2 4.3 5 MARCO TEÓRICO ......................................................................................................... 11 5.1 5.2 5.3 5.4 5.5 5.6 5.7 5.8 III 6 Música y Computación ........................................................................................................... 7 Restricciones y Música ............................................................................................................ 8 Aportes de la programación con restricciones a la Música................................................ 8 Estructuras musicales y Armonía.........................................................................................11 Escalas ......................................................................................................................................11 Tonalidad.................................................................................................................................12 Música Tonal ...........................................................................................................................12 Oz..............................................................................................................................................13 Mozart ......................................................................................................................................13 Programación por Restricciones ...........................................................................................13 Propagadores...........................................................................................................................14 MODELO E IMPLEMENTACIÓN ..................................................................... 15 MODELOS ESTUDIADOS............................................................................................ 15 6.1 CONSIDERACIONES PRELIMINARES .............................................................................15 6.1.1 Variables..............................................................................................................................16 6.2 MODELAMIENTO DE LAS ESTRUCTURAS....................................................................17 6.2.1 Variables y Dominios ........................................................................................................18 6.2.2 Restricciones .......................................................................................................................21 7 MUZA: DEFINICIÓN DEL SISTEMA DE RESTRICCIONES ............................... 24 7.1 Variables y Dominios .............................................................................................................24 7.1.1 Notas....................................................................................................................................24 7.1.2 Secuencia de Notas ............................................................................................................25 7.1.3 Acordes................................................................................................................................26 7.2 Restricciones ............................................................................................................................29 7.2.1 Restricciones sobre Notas .................................................................................................29 7.2.2 Restricciones sobre Secuencias de notas .........................................................................36 7.2.3 Restricciones sobre Acordes .............................................................................................44 8 PRUEBAS Y RESULTADOS OBTENIDOS................................................................ 69 8.1 Pruebas Internas .....................................................................................................................69 8.2 EJEMPLOS ...............................................................................................................................75 8.2.1 Ejemplo 1.............................................................................................................................75 8.2.2 Ejemplo 2.............................................................................................................................77 9 10 CONCLUSIONES ............................................................................................................ 79 VALOR DE LA INVESTIGACIÓN .............................................................................. 81 10.1 IV 11 TRABAJO FUTURO ...............................................................................................................81 ANEXOS ................................................................................................................. 82 DETALLES SOBRE LA IMPLEMENTACIÓN........................................................... 82 11.1 Construcción de MuZa ..........................................................................................................82 11.1.1 Compilación: Ozc ..........................................................................................................82 11.1.2 Creación de MuZa.........................................................................................................82 11.2 Utilización de MuZa...............................................................................................................83 V Referencias Bibliográficas ....................................................................................... 84 INTRODUCCIÓN INTRODUCCIÓN La creatividad, una de las características más interesantes de los seres humanos, ha llevado a estos a componer piezas musicales únicas capaces de reflejar lo que el compositor quiere de una forma que resulta agradable al oído. Múltiples estudios sobre teoría musical e inteligencia artificial se han adelantado para generar mecanismos y herramientas para la composición musical automática. El presente proyecto tiene como objetivo principal desarrollar un sistema de restricciones musicales de armonía para Mozart que permita resolver problemas musicales ceñidos a restricciones dadas por un compositor, ya que aunque existen diversas estrategias de composición musical artificial, muchas están ligadas a modelos predefinidos, o situaciones aleatorias. La programación por restricciones permite modelar el problema de la composición musical asistida por computador a través de reglas o restricciones definidas por un compositor, ofreciendo así un mecanismo rico en expresividad para la composición de diversas piezas que reflejarán, a modo más fiel, la intención del compositor. Diversos trabajos desarrollados con este paradigma han demostrado que las relaciones existentes entre las estructuras musicales de una melodía pueden tomarse como restricciones que actúan sobre dichas estructuras al ser transformadas a variables de dominios finitos. El trabajo aquí expuesto da como fruto un sistema de restricciones musicales de armonía para Mozart que permite explotar los beneficios de la programación por restricciones en Oz, un lenguaje multi-paradigma muy poderoso que presenta una integración con restricciones muy útil, en pro del desarrollo de una herramienta que facilita el modelamiento de problemas de satisfacción de restricciones musicales. Con el fin de cumplir los objetivos planteados, se efectuó un proceso de investigación en busca de las herramientas teóricas para diseñar e implementar un sistema de restricciones musicales eficiente, fácil de usar y de extender, que permita llegar a soluciones adecuadas a través de modelamientos musicales naturales (directamente con estructuras musicales y no con adaptaciones a dominios finitos u otros modelos abstractos), de modo que para el usuario sea transparente el uso de los modelos abstractos y/o dominios finitos que soporten las estructuras musicales. 1 OBJETIVOS, PLANTEAMIENTO Y JUSTIFICACIÓN I 1 1.1 OBJETIVOS, PLANTEAMIENTO Y JUSTIFICACIÓN OBJETIVOS OBJETIVO GENERAL Diseñar e implementar un conjunto de restricciones y estructuras musicales en Mozart que permitan solucionar problemas musicales referentes a la armonía definidos por un compositor. 1.2 OBJETIVOS ESPECÍFICOS 1. Estudiar la teoría de la programación por restricciones en Mozart. 2. Analizar diversas estructuras musicales y sus relaciones armónicas. 3. Investigar sobre problemas combinatorios en el área de la música. 4. Definir un conjunto de estructuras y restricciones suficientes para resolver problemas musicales armónicos con un nivel moderado de complejidad. 5. Diseñar e implementar un conjunto de estructuras musicales en Mozart. 6. Diseñar e implementar un sistema de Restricciones de armonía en Mozart. 7. Diseñar e implementar propagadores para el sistema de restricciones desarrollado en Mozart. 8. Desarrollar un conjunto de ejemplos representativos del alcance del sistema de restricciones diseñado. 2 OBJETIVOS, PLANTEAMIENTO Y JUSTIFICACIÓN 2 FORMULACIÓN DEL PROBLEMA La composición musical, la representación de estructuras musicales, y las relaciones entre dichas estructuras son temas recurrentes cuando se desea modelar computacionalmente un problema musical. Muchos problemas musicales pueden modelarse y resolverse con el paradigma de programación por restricciones, que resulta muy apropiado dadas las características combinatorias que presentan la mayoría de problemas de satisfacción de restricciones musicales. Sin embargo, resulta necesario al trabajar en Mozart, que el modelo adoptado se ajuste a las representaciones que el lenguaje (Oz) ofrece para las estructuras de datos que muchas veces resultan demasiado abstractas en relación al problema. Por consiguiente, es necesario preocuparse por realizar una transformación de los modelos musicales a formas matemáticas abstractas que, aunque pueden ser robustas, no son necesariamente las ideales para alguien que desee resolver un problema musical (dígase un compositor). Por lo tanto, resulta preciso para dar una solución a este planteamiento, encontrar la forma de modelar un conjunto de estructuras musicales, las relaciones entre ellas y las posibles restricciones que se puedan imponer a dichas estructuras de modo que sea posible satisfacer los requerimientos de un compositor. 3 JUSTIFICACIÓN La música tiene la capacidad de afectar las emociones, influye en el estado de ánimo de las personas y goza de una gran importancia por esas cualidades humanas tan únicas y llenas de subjetividad que la caracterizan; estas propiedades han hecho de la música parte de la historia de la humanidad desde sus comienzos como medio de expresión y comunicación. En particular, la música tonal (de naturaleza armónica) tiene mayor capacidad de transmitir y reflejar estados anímicos o sonoros sobre quienes la escuchan. Las obras musicales que resultan agradables al oído suelen presentar características definidas tales como melodía, ritmo y temporalidad entre otras. La música tonal ha sido objeto de numerosos estudios en busca de formalizaciones precisas que permitan expresar la relación entre sus componentes de modo puntual, y como producto de años de investigación ancestral se han establecido no sólo numerosos tratados de armonía [22], sino también estudios que resaltan las 3 OBJETIVOS, PLANTEAMIENTO Y JUSTIFICACIÓN relaciones que existen entre la música las matemáticas y la física2. Pitágoras fue el primero en descubrir la relación que existe entre los tonos que suenan “armónicos” y que la música puede ser expresada o medida a través de razones de números enteros; descubrió que al dividir una cuerda en ciertas proporciones se producen sonidos placenteros al oído que se relacionan entre sí no sólo por la proporción del tamaño de la cuerda, sino porque eran “semejantes”, (si se corta la cuerda a la mitad se produce el mismo sonido una octava más arriba, es decir más agudo). Además, la semejanza clara entre la serie de Fibonacci y la forma como Beethoven desarrolla su quinta sinfonía y el estrecho vínculo entre las composiciones de Bach con patrones matemáticos [1], son muestras tangibles de la relación existente entre música y números [24]. El estudio de las distintas características inherentes de la música ha dado como resultado un campo amplio conocido como teoría musical, en el que se explican las relaciones entre las figuras musicales, las escalas tonales a las que pertenecen, el manejo temporal que se les da y la secuencia precisa que presentan, entre otros. Este conjunto de relaciones puede verse como un sistema amplio y complejo de restricciones que se aplica a las notas musicales para darle vida a los acordes y melodías que forman piezas musicales tonales de forma correcta, es decir, piezas musicales que cumplen con un conjunto de características propias que las hacen agradables al oído. Debido a que los diversos campos artísticos resultan tan interesantes para modelos computacionales ya que están sujetos a la creatividad propia del ser humano y a la subjetividad de quienes juzgan las obras, resulta llamativo adentrarse en líneas de investigación que pretendan modelar dichos campos. En el caso de la música tonal, gracias a la relación latente que existe entre ella y las matemáticas, es posible desarrollar modelos capaces de describir sus rasgos en detalle, (a diferencia de otros campos artísticos que no cuentan con modelos formales). Esta característica permite que en el campo de la computación sea posible explorar la naturaleza misma de la música en busca de modelos que permitan recrear las características armónicas de las piezas musicales que resultan agradables al ser humano. El paradigma de programación por restricciones ha permitido modelar diversos aspectos de la realidad encontrando soluciones eficientes a problemas que por su naturaleza permiten ser tratados por ésta área. Gracias a la naturaleza de la música tonal, las restricciones que se pueden aplicar a las estructuras musicales La relación entre la música y la física corresponde a la naturaleza del sonido como tal, por lo tanto aplica a la música tonal como atonal 2 4 OBJETIVOS, PLANTEAMIENTO Y JUSTIFICACIÓN pueden satisfacer las condiciones tonales, temporales y armónicas necesarias para que una pieza musical sea agradable. En Mozart no existe un sistema de restricciones para la música, por lo tanto crear uno que modele dicha realidad y que permita a un compositor determinar las características deseadas para la solución de un problema musical, resulta de gran interés dentro de la comunidad de ciencias de la computación. 5 MARCO DE REFERENCIA II MARCO DE REFERENCIA 4 ESTADO DEL ARTE La música ha sido objeto de múltiples investigaciones a lo largo del tiempo, ya que su naturaleza agradable ha motivado al hombre a buscar su entendimiento y generación con una gran diversidad de estilos que han dado como fruto una enorme cantidad de géneros musicales, cada uno con una influencia especial de épocas, tonalidades, estados anímicos, situaciones sociales y raíces culturales. Desde las ciencias de la computación se han estudiado múltiples características de la música y la forma como éstas pueden ser modeladas computacionalmente con el fin de crear piezas musicales, reconocer patrones de géneros musicales específicos, prestar ayuda a compositores y directores con el fin de generar partituras y resolver problemas musicales diversos. En [2] se identifican cuatro actividades que involucran el desarrollo de aplicaciones computacionales que compongan música, donde cada actividad está inspirada por diferentes motivaciones, ya sean prácticas o teóricas, estas actividades se describen en detalle en la tabla 1. Dominio Composición Ingeniería de Software Musicología Ciencias Cognitivas Actividad Motivación Composición Algorítmica Expansión de repertorios de composiciones Desarrollo de Diseño de herramientas herramientas para para la composición compositores Propuesta y evaluación de Modelos computacionales teorías sobre estilos de estilos musicales musicales Propuesta y evaluación de Modelos computacionales teorías cognitivas de de conocimiento musical composición musical Tabla 1 Motivaciones para desarrollar programas compositores 6 MARCO DE REFERENCIA 4.1 Música y Computación La composición musical ha sido una de las áreas más exploradas por las distintas ramas de la computación, ya que involucra factores de Inteligencia Artificial muy interesantes para los investigadores, cuyo estudio permite sacar conclusiones sobre la creatividad de los agentes y la naturaleza de la música. Entre las herramientas computacionales que han sido utilizadas para explorar la composición musical asistida por computador, (CAC)3, se encuentran los algoritmos genéticos, las redes neuronales, los fractales, el uso de modelos estocásticos y la programación por restricciones. La computación evolutiva ha utilizado algoritmos genéticos para componer piezas musicales. Algunos de estos algoritmos modelan las piezas musicales como conjuntos de proteínas, e incluso han utilizado los modelos de ADN y proteínas para generar melodías valiéndose de una semejanza básica [1]: Ambos, tanto cadenas de ADN o proteínas como melodías musicales, consisten en una secuencia lineal de elementos cuyo verdadero significado yace en la combinación de los mismos. Las melodías generadas por estas técnicas son representaciones sonoras de cadenas de ADN, por lo tanto la composición está basada en la abstracción de los modelos dados por secuencias de proteínas [3], y no por características impuestas o deseadas por un compositor en particular. Sin embargo, la composición musical basada en algoritmos genéticos ha sido tratada basándose, también, en las efectivas técnicas de búsqueda de los algoritmos genéticos en espacios de búsqueda muy grandes; estos algoritmos son utilizados cuando el dominio de la solución ha sido pobremente definido o cuando no hay una forma clara de juzgar la solución objetivamente, por lo tanto resultan ideales para resolver problemas difíciles cuyo dominio no ha sido especificado claramente [4]. Desde el área de las redes neuronales se ha estudiado la computación musical para aprender más acerca de los procesos y representaciones involucrados en la percepción, producción, comprensión y composición de la música, y así crear modelos computacionales basados en el estilo de computación cerebral para ver si es posible capturar con precisión la labor musical humana en un sistema artificial [5]. Así mismo, a partir de los fractales también se han realizado estudios sobre modelos musicales que siguen un comportamiento fractal, dando lugar a lo que se ha denominado “música fractal”, que no es más que la representación musical de 3 Computer Assisted Composition 7 MARCO DE REFERENCIA fórmulas fractales donde los números son relacionados con notas e instrumentos, dando así una representación sonora de fórmulas matemáticas que pueden describir casi cualquier cosa, desde estructuras de ADN hasta formas visibles en la naturaleza como las nubes o las hojas de los árboles [6]. Por otra parte, el uso de modelos estocásticos en [18] para la composición musical basada en contextos musicales pasados, ha generado también resultados muy interesantes con características presentes tales como la improvisación y la ayuda a la composición. 4.2 Restricciones y Música El uso del paradigma de programación por restricciones aplicado a modelos musicales resulta muy natural debido a las propiedades de la música, y las relaciones estrictas que existen entre componentes musicales en una melodía o pieza musical [14]; por ejemplo las notas de una melodía deben pertenecer a cierta escala, tonalidad, mantener una temporalidad específica, etc. Las reglas de armonización que rigen a las piezas musicales, aunque difieren según el tipo de melodía, son en verdad un conjunto de restricciones impuestas sobre un grupo de estructuras musicales que actúan como variables en un problema. Además de los problemas que involucran armonización, la programación por restricciones ha sido aplicada a otros campos de la computación musical tales como el control de espacialización [8], la improvisación controlada, y la generación de patrones rítmicos a través de las restricciones temporales concurrentes [9] entre otros. Sin embargo, el objeto de la investigación se basa más en restricciones de armonía musical, por lo tanto serán casos de aplicación de restricciones de armonía musical los que se presentarán en este documento. 4.3 Aportes de la programación con restricciones a la Música COMPOzE [10] es una plataforma basada en la programación por restricciones sobre dominios finitos de enteros, desarrollada con el propósito de derivar piezas musicales de cuatro voces a partir de planos musicales dados que describen el flujo armónico y las características de una composición deseada. Esta plataforma está soportada por el sistema de programación por restricciones Oz, a través de un modelo de restricciones en dominios finitos. Por medio de esta herramienta es 8 MARCO DE REFERENCIA posible componer piezas musicales con características predefinidas por el compositor de forma automática gracias a la programación por restricciones. OpenMusic [12] [11] es un ambiente de programación musical visual orientado a objetos para compositores que funciona sobre sistemas Macintosh, Linux y Windows. Es una herramienta que permite a los compositores crear melodías según las características deseadas, de una forma visual que además provee un conjunto de objetos musicales predefinidos para manejar sonido, notación musical y archivos midi; estos objetos están representados por íconos que pueden ser arrastrados y pegados en el área de trabajo. Las restricciones en OpenMusic son manejadas para dar solución a problemas musicales de carácter armónico y/o rítmico a través de la librería Situation [17], que permite la descripción de secuencias musicales a partir de la descripción de sus propiedades; Situation es utilizada para generar objetos musicales cuando cada objeto en una secuencia es una entidad descrita por un conjunto dado de propiedades que conectan sus elementos, o cuando los objetos en posiciones seleccionadas de la secuencia deben satisfacer una serie de restricciones. Situation cuenta con cinco “sub-paquetes”, donde uno de ellos es de Solvers y cuyos módulos son los motores de resolución de restricciones encargados de dar solución a los problemas de satisfacción de restricciones en OpenMusic; estos solvers son: csolver (constraints solver), wsolver (weak solver), y add-solver (additional constraints solver); donde cada uno de ellos es un sistema de dominios finitos que abstrae los objetos musicales utilizados en OpenMusic. La integración entre objetos concurrentes y restricciones en aplicaciones musicales ha sido estudiada en [13], dando lugar a PiCO, un cálculo que integra objetos concurrentes y restricciones, sugiriéndolo como una base para herramientas de composición musical dadas las ventajas que el modelo de objetos y comunicación a través de mensajes puede dar a las estructuras musicales. También en [21] se utilizan los paradigmas de programación por restricciones y programación orientada a objetos en un lenguaje visual concurrente llamado Cordial, que provee una clara noción de objetos definidos implícitamente por restricciones. Las principales características de Cordial son: Un modelo visual jerárquico donde las clases, métodos e instancias pueden ser expandidos para ver sus componentes; un formalismo visual dando sintaxis precisa y semántica estática de programas visuales; y un modelo de semántica dinámica basado en un cálculo formal integrando objetos y restricciones. 9 MARCO DE REFERENCIA Strasheela [25] es un ambiente de composición musical basado en Oz; permite resolver problemas musicales de composición a través de la definición de un conjunto de estructuras musicales, cuyos parámetros pueden ser restringidos haciendo uso del conjunto de restricciones propio de Mozart. Aunque Strasheela permite expresar la música de un modo familiar al compositor, no define restricciones propias hacia las estructuras musicales definidas; por consiguiente, el compositor deberá implementar las restricciones clásicas de Mozart sobre un conjunto de estructuras musicales para dar solución a su problema, lo que le obliga a saber abstraer las restricciones que le da Mozart para cumplir un objetivo determinado en la composición, ( como melodía, armonía o temporalidad entre otros). Estas herramientas para CAC, utilizan eficientemente las restricciones para hallar las soluciones definidas para los problemas que manejan. Una gran ventaja que tienen los sistemas de restricciones musicales es que no están ligados a un tipo de composición aleatoria o fija a una estructura inicial, (como en los casos expuestos anteriormente), sino que fijan una solución según las reglas fijadas previamente por un compositor. A pesar de que Mozart soporta muchas aplicaciones basadas en restricciones y ha sido utilizado en varios estudios de composición musical, (tales como COMPOzE), y que se ha comprobado que el modelado de estructuras musicales se adapta perfectamente a la programación por restricciones debido a las características propias de las relaciones presentes entre dichas estructuras musicales en una pieza musical, no existe actualmente un conjunto de estructuras musicales ni restricciones definidas en MOzART que permitan modelar problemas de satisfacción de restricciones musicales directamente sin la necesidad de abstraer explícitamente las estructuras musicales en dominios finitos. Por esta razón resulta bastante útil la implementación de un conjunto de estructuras musicales y restricciones para las mismas en Mozart que permitan tratar problemas de satisfacción de restricciones musicales directamente sin necesidad de abstraer el modelo a dominios finitos. 10 MARCO DE REFERENCIA 5 5.1 MARCO TEÓRICO Estructuras musicales y Armonía La armonía musical es la relación equilibrada existente entre las notas cuando suenan simultáneamente y el modo en que estas relaciones se organizan en el tiempo [23]; también cualquier colección concreta de notas que suenan simultáneamente, que recibe el nombre de acorde y que en conjunto se enlazan a lo largo de una melodía, dándole así a la pieza musical la capacidad de determinar diversos estados de consonancias, (diferentes ambientes de reposo), y disonancias [16] (diferentes estados de tensión). Los intervalos4 consonantes suenan estables y completos, mientras que los disonantes suenan inestables y piden una resolución en un intervalo consonante. Entonces la armonía es responsable de hacer que múltiples sonidos, ya sean concurrentes o secuenciales, puedan dar de cierto modo dinamismo a una pieza musical debido a la relación estricta que guardan entre ellos. Sin embargo, no es sólo la armonía la que le da a las piezas musicales sus características únicas, interfieren gran variedad de elementos como la melodía, el ritmo, la forma y el manejo del tiempo entre otros; la coexistencia de todos estos elementos es los que permite dar vida a obras musicales completas, y las relaciones que se definen en cada uno de esos elementos sobre las estructuras musicales, (como notas, acordes, silencios, etc), son en la mayoría de los casos (música tonal) cuidadosamente modeladas y especificadas. 5.2 Escalas [22] De las escalas se extraen los sonidos que forman un intervalo. Las escalas más familiares son las dos escalas diatónicas de siete notas cada una llamadas escala mayor y escala menor. Las siete notas de la escala diatónica se llaman grados de la escala, donde cada uno tiene su parte en el esquema de la tonalidad definiendo una función tonal; éstos suelen indicarse con números romanos del I al VII y se les designan los siguientes nombres: I. Tónica: la nota básica. II. Supertónica: la nota siguiente sobre la tónica III. Mediante: A medio camino, hacia arriba entre la tónica y la dominante Intervalo: [22] Unidad básica de la armonía que describe la distancia entre dos sonidos. Cuando dos sonidos suenan a la vez, la distancia entre ellos es un intervalo armónico. Si los dos sonidos se oyen uno tras otro, la distancia es un intervalo melódico. 4 11 MARCO DE REFERENCIA IV. Subdominante: A la misma distancia de la tónica hacia abajo que la dominante hacia arriba V. Dominante: Un elemento realmente dominante en la tonalidad VI. Submediante: A medio camino, hacia abajo, entre la tónica y la subdominante. VII. Sensible: Con una tendencia melódica a ir hacia la tónica. Se usa este término cuando la distancia entre el séptimo grado y la tónica es de medio tono, pero cuando es de un tono se le llama séptimo grado menor o subtónica. Según la cantidad de notas que hay entre los grados de la escala que conformen un intervalo se denomina al mismo: Por ejemplo un intervalo formado por los grados I y II es un intervalo de segunda ya que desde I hasta II hay que pasar por dos notas (incluyendo a I y II). Del mismo modo un intervalo de tercera será aquel formado por los grados I y III, III y V, V y VII entre otros, ya que podría darse un intervalo de tercera con los grados II y VII contando las notas que hay entre el septimo grado y el segundo de forma cíclica e incluyendo los grados VII y II: (VII, I, II). 5.3 Tonalidad [22] La tonalidad es el conjunto organizado de notas alrededor de una tónica, es decir que hay una nota central soportada de una u otra forma por las demás notas. Sin embargo, no es simplemente una manera de utilizar las notas de una escala particular, es más bien un proceso de establecimiento de relaciones de estas notas con la nota que representa el centro tonal. 5.4 Música Tonal La música Tonal se basa en escalas diatónicas, se distingue sobretodo por la importancia de sus elementos armónicos, y es característica de la época que data desde finales del siglo XVI hasta mediados del siglo XX. Los elementos armónicos característicos de la música tonal están dados por las relaciones entre los acordes, y cómo estos transcurren siguiendo progresiones armónicas. Una sucesión armónica se constituye por dos acordes cualquiera uno tras de otro, mientras que una progresión armónica [23] consta de una sucesión de acordes en la que el movimiento de las sucesivas fundamentales, (las notas sobre las que están construidos los acordes), se percibe más o menos claramente, es decir, guardan una relación estrecha. 12 MARCO DE REFERENCIA 5.5 Oz Oz [19] es un lenguaje multi-paradigma que está diseñado para desarrollar aplicaciones avanzadas, concurrentes, en red y en tiempo real. Oz provee las características de la programación orientada a objetos, funcional, lógica y por restricciones. Además, Oz es un lenguaje concurrente en el que los usuarios pueden crear dinámicamente cualquier número de hilos secuenciales que pueden interactuar entre ellos. 5.6 Mozart Mozart [19] es un sistema de programación que implementa Oz3, el útimo en la famila Oz de lenguajes multi-paradigma basado en el modelo concurrente de restricciones, esto hace de Mozart inigualable en potencia, expresividad y funcionalidad. Mozart es una plataforma ideal para propósitos generales tanto para aplicaciones distribuidas como para problemas difíciles que requieren habilidades sofisticadas de optimización e inferencia [20], ya que soporta la distribución de las computaciones hechas por Oz de forma transparentes en red, aprovechando así de manera eficiente todas las bondades de Oz para la resolución de problemas. 5.7 Programación por Restricciones La programación por restricciones es un paradigma de programación que permite resolver u optimizar problemas difíciles muchas veces de carácter combinatorio. Un problema es expresado a través de un conjunto restricciones y un conjunto de variables denominadas variables del problema, donde las restricciones establecen relaciones entre dichas variables; una solución a un problema expresado de este modo es la asignación de un conjunto de valores a las variables del problema de modo que se satisfagan todas las restricciones dadas. Para calcular la asignación de un valor a una variable del problema, primero se establece un conjunto de valores potenciales para dicha variable, este conjunto de valores potenciales se conoce como dominio. Una variable ha sido asignada o determinada cuando su dominio contiene sólo un elemento. El proceso mediante el cual una variable es determinada se conoce como propagación de restricciones, y consiste en remover sucesivamente valores del dominio de una variable que son incompatibles con las restricciones impuestas sobre ella. [26] El uso de la programación por restricciones permite modelar problemas especificando información parcial sobre las variables desconocidas, de modo que el espacio de búsqueda para los valores de las variables del problema se vea limitado 13 MARCO DE REFERENCIA a cumplir las características impuestas por las restricciones dadas. Las dos técnicas básicas de la programación por restricciones son la propagación y la distribución de restricciones [7], donde la propagación de restricciones es un mecanismo de inferencia obtenido con propagadores concurrentes que acumulan información en un “almacén” de restricciones aplicando las restricciones dadas a todo el conjunto de variables del problema. Cuando la propagación de restricciones no puede continuar, (ha llegado a un punto donde todas las restricciones se han aplicado y el dominio de las variables no cambia), la distribución de restricciones divide el problema en dos casos complementarios: uno en el que se evalúa una posible solución dada por “asignar”, (ensayar), uno de los valores del dominio de una variable; y otro dado por una posible solución que excluya dicho valor para esa variable; de modo que con los resultados obtenidos en la propagación se realiza la búsqueda de soluciones, descartando o no posibles resultados. Finalmente, y luego de iterar continuamente estas dos técnicas, se hallará una solución gracias a la inferencia de la propagación, llegando así a dar soluciones que satisfagan las condiciones impuestas por el problema en tiempos razonables. 5.8 Propagadores Los propagadores son agentes computacionales que son impuestos en las variables de una restricción, conocidas también como parámetros del propagador. Una Restricción básica es aquella cuya fórmula involucra dominios finitos de modo directo y tiene una representación simple, (tal como x=y, x=n o x Є D donde x e y son variables, n un número y D un dominio finito); las restricciones básicas residen en el “Almacén” de Restricciones, (Constraint Store), y su satisfacción es decidida eficientemente por algoritmos dados por Oz encargados de hacerlo. Cuando se manejan restricciones más complejas y expresivas que las básicas, la decisión de la satisfactibilidad de sus variables no resulta trivial, y es allí cuando la labor prestada por los Propagadores adquiere sentido: Los propagadores intentan reducir el dominio de las variables; esto lo logran verificando que se cumplan las restricciones sobre las variables del problema albergadas en el almacén de restricciones, cuyo tamaño se incrementa con restricciones básicas que son el resultado de expresar las restricciones complejas de formas más sencillas. A esta reducción de dominios se le conoce como propagación de restricciones. En [15] se indican los mecanismos para implementar restricciones nuevas en Mozart. 14 MODELO E IMPLEMENTACIÓN III MODELO E IMPLEMENTACIÓN 6 MODELOS ESTUDIADOS Con el propósito de diseñar un modelo rico en expresividad en cuanto al sentido musical, óptimo en rendimiento en cuanto los cálculos computacionales y que a la vez sea fácilmente extensible, se estudiaron varias opciones para modelar las estructuras musicales fundamentales para el sistema de restricciones. A continuación se exponen detalladamente los modelos más significativos que surgieron a lo largo de la etapa exploratoria del proyecto. Estos modelos son fruto de lo que sugiere la literatura sobre armonía estudiada [22], [28]. Las estructuras musicales básicas seleccionadas para abordar la temática de estudio son las notas y los acordes. Las notas son la unidad básica de cualquier composición musical ya que representan un sonido en particular, y los acordes son conjuntos de notas que suenan a la vez. A partir de estas dos estructuras se pueden hacer secuencias de las mismas que representen sucesiones melódicas, (en el caso de las notas), sucesiones armónicas, (secuencia de acordes cualquiera), y progresiones armónicas, (sucesión armónica bajo ciertas reglas sobre el movimiento las notas fundamentales de los acordes). Al modelar estas dos estructuras fundamentales es posible recrear las relaciones que pueden darse entre ellas por medio de restricciones sobre sus dominios, dando como resultado un conjunto de restricciones musicales de fácil manejo para el usuario final, y sencillas de entender para el (los) desarrollador(es) que deseen extender el sistema de restricciones. El sistema de restricciones ofrecerá mayor expresividad para el manejo de estructuras musicales 6.1 CONSIDERACIONES PRELIMINARES Antes de llegar a la formulación de los modelos más relevantes, es fundamental delimitar las estructuras o variables que se van a usar, porque aunque ya se dijo que las estructuras a representar serán notas y acordes, no se ha dicho aún exactamente qué características de dichas estructuras serán abarcadas por el modelo; debido a que el alcance del proyecto sólo considera características armónicas sencillas de las estructuras musicales, atributos referentes a temporalidad, alteraciones, dinámica y demás no serán tenidos en cuenta. 15 MODELO E IMPLEMENTACIÓN 6.1.1 6.1.1.1 Variables Notas Existen siete notas musicales, cada una de ellas puede ubicarse en un pentagrama en distintos lugares según la octava en la que se encuentre; es decir una nota puede sonar más grave o más aguda según la posición, (octava), en la que se ubique. En el ejemplo siguiente, se ven las siete notas y al final aparece la nota do pero una octava más arriba que la primera. Figura 1 Notas en un pentagrama El siguiente pentagrama representa las mismas notas que el anterior pero en la notación inglesa, donde cada nota recibe el nombre de una letra mayúscula C, D, E, F, G, A o B. Figura 2 Notas en un pentagrama, Notación inglesa En las teclas de un piano estas notas mencionadas corresponden a las teclas blancas, y se ven así: Figura 3 Notas en las teclas de un piano 16 MODELO E IMPLEMENTACIÓN Las teclas blancas corresponden a las siete notas descritas anteriormente, y las negras a las notas intermedias que existen entre ellas y reciben el nombre de sostenidos (#) o bemoles (b), es decir, siendo C un tono y D otro, C#, ( o Db), se encuentra a un semitono de ambas notas. Como se puede apreciar en la figura, entre E y F , (Mi y Fa), no hay una tecla negra, lo que significa que la distancia entre ellas es de un semitono y no de un tono como en las demás notas; lo mismo ocurre entre B y C , (Si y Do). La figura representa dos octavas o regiones; la diferencia entre las notas de estas octavas es que a pesar de ser las mismas, las de la octava uno tendrán un sonido más grave que las de la octava dos, ya que la frecuencia del sonido que emiten las notas de la segunda octava tiene una relación de dos a uno con respecto a las de la primera octava. 6.1.1.2 Acordes Un acorde es un conjunto de tres o más notas que suenan o se tocan simultáneamente o en arpegio5. En un pentagrama se representan las notas que lo conforman alineadas verticalmente así: Figura 4 Acorde 6.2 MODELAMIENTO DE LAS ESTRUCTURAS A continuación se explica el modelo que se adoptó para las diferentes estructuras musicales. Para la definición de un acorde se consideraron varios modelos, y se explican los dos más relevantes dentro del estudio. El primer modelo a considerar surgió como consideración de la definición particular hecha por W. Piston [22] de un acorde. El segundo modelo considera una representación diferente para los acordes, esta representación es mucho más simple, por lo tanto resulta más eficiente y sencilla en términos de implementación sin perder la coherencia en cuanto a teoría musical, (expresividad), para quien desee extenderla. Arpegio: Modalidad para tocar un acorde en la que en lugar de tocar las notas de forma simultanea se tocan rápidamente de forma sucesiva. 5 17 MODELO E IMPLEMENTACIÓN 6.2.1 6.2.1.1 Variables y Dominios Notas Una nota es una estructura de tipo tupla con dos atributos: Tono y Octava; donde Tono es una variable cuyo dominio se encuentra entre do y si, (C y B), pasando por todos los semitonos incluidos entre estas notas; y Octava es un número que representa la ubicación de la nota en el pentagrama, es decir la agudeza de la misma o la región en la que se encuentre. Bajo esta definición, una nota n podría verse así: n ::= (nτ , nο ) En donde el primer campo de la tupla nτ representa el tono de la nota y el segundo campo de la tupla nο representa la octava en la que esta se encuentra. Como se dijo anteriormente los dominios correspondientes de los atributos de tipo nota son respectivamente: nο :: [C , C # , D, Eb, E K A, Bb, B ] nτ :: [0 K 4] Para representar este modelo en Oz fue necesario transformar el atributo tono a dominios finitos, de modo que la estructura nota pudiera ser manipulada por las restricciones propias del lenguaje, que están definidas en función de dominios finitos. Aunque este cambio es necesario para la implementación, es transparente al usuario, ya que este definirá el tono de la nota según el dominio propio de la misma, y no según las transformaciones hechas al modelo gracias al uso de la función de transformación cada vez que se crea una nota. La función de transformación relaciona un valor entero a cada semitono de una octava según lo indica la Tabla 2: Función de transformación para tonos. C C# o Db D D# o Eb E F :0 :1 :2 :3 :4 :5 F# o Gb G G# o Ab A A# o Bb B :6 :7 :8 :9 : 10 : 11 Tabla 2: Función de transformación para tonos 18 MODELO E IMPLEMENTACIÓN La función de transformación sobre tonos se ilustra en la Figura 5 sobre las teclas de un piano. Figura 5: Notas en las teclas de un piano según la función de transformación Como consecuencia de la transformación hecha sobre el atributo tono, se observa que una nota podría identificarse solamente por un número entero vlr, resultado de sumar el tono al producto entre doce y la octava, teniendo en cuenta los dominios de las variables tono y octava considerados para este modelo se obtiene el dominio de la variable vlr. vlr = (12 × nο ) + nτ vlr :: [0 K 59] Esta abstracción podría tomarse como base para el resto de la implementación representando una nota como un número entero, pero debido a que se pretende que el modelo sea fácilmente extensible y que sea rico en expresividad tanto para el usuario final como para quienes deseen extender la implementación, resulta más favorable representar la nota como la tupla propuesta agregándole el atributo valor; de este modo una nota será una tupla con tres atributos así: n ::= (vlr , nτ , nο ) Entonces, los dominios de los atributos de una nota n, teniendo en cuenta la transformación a dominios finitos de sus atributos, son: 19 MODELO E IMPLEMENTACIÓN n τ :: [0 K 4 ] n ο :: [0 K11] vlr :: [0 K 59 ] 6.2.1.2 Acordes: Primer modelo Un acorde es un conjunto de notas producto de la unión de dos o más intervalos armónicos diferentes [22], por lo tanto tendrá como mínimo tres notas en caso de que los intervalos armónicos que lo conforman tengan una nota en común. Esta definición se modela a través de un vector de conjuntos de dos notas, en la cual las notas se representan por medio del atributo vlr de la tupla nota descrita anteriormente; esto se hace con el objetivo de aprovechar la definición de conjuntos finitos y las restricciones sobre los mismos que tiene Oz en el módulo FS, (Finite Set Constraints). Un acorde ch se define así: ch ::= [ConjNota, ConjNota + ] ConjNota ::= {Nota, Nota}, donde ∀x, y ∈ ch{ x ∩ y <= 1} Nota :: [0K59] 6.2.1.3 Acordes: Segundo modelo En este caso, un acorde es considerado como un conjunto de notas, sin tener en cuenta los intervalos que lo conforman. Para hacer uso de las facilidades que brinda el módulo FS, (Finite Set Constraints), de Oz se manejan las notas pertenecientes al acorde por medio del atributo valor de la tupla nota. Entonces, un acorde Ch se define como: Ch ::= {x : 0 ≤ x ≤ 59} 3 ≤ Ch ≤ 60 El tamaño del acorde se limita hasta 60 notas, (que sería un caso muy extraño), ya que el dominio de las notas se restringe por la cantidad de octavas a considerar, que en este caso son cinco. Para manejar esta definición del mismo modo que Mozart maneja los conjuntos finitos en el módulo FS, a continuación se muestra el acorde según el modelo de conjuntos que maneja Mozart: Ch =: (UpperBound , LowerBound , CardRange ) 20 MODELO E IMPLEMENTACIÓN Según esta definición un acorde está definido en términos de tres atributos: UpperBound: Lista que denota los elementos del dominio del acorde, es decir enteros entre cero y 59 que representan todas las notas del dominio. LowerBound: Lista que denota los elementos que pertenecen al acorde. CardRange: Variable de tipo entero que denota el tamaño del acorde, (cardinalidad del conjunto). 6.2.1.4 Secuencias de Notas Una secuencia Sn de notas es representada por un vector cuyos elementos son notas: Sn ::= [n + ] n ::= (vlr , nτ , nο ) nτ :: [0K 4] nο :: [0K11] vlr :: [0K59] 6.2.2 6.2.2.1 Restricciones Restricciones sobre notas 6.2.2.1.1 Restricciones sobre una nota 1. Tono: Establece un rango valores para el atributo tono de la tupla nota. Esta restricción tiene como parámetros una nota, y un rango de tonos. 2. Octava: Establece un rango de valores para el atributo octava de la tupla nota; recibe como parámetros una nota y un rango de octavas. 6.2.2.1.2 Restricciones sobre dos notas 1. Distancia: Fija un rango de distancia, en términos de semitonos, entre dos notas dadas. Los parámetros de esta restricción son: un rango de distancia en términos de semitonos, y dos notas a y b. 2. Tonos: Establece una relación entre el tono de ambas notas. Los parámetros de esta restricción son: dos notas a y b, y la relación entre los tonos de las mismas. 21 MODELO E IMPLEMENTACIÓN 3. Octavas: Establece una relación entre la octava en la que se ubica cada nota. Esta restricción recibe como parámetros dos notas a y b, y la relación que existe entre las octavas de las mismas. 6.2.2.1.3 Restricciones sobre secuencias de notas 1. Tono: Restringe el rango de valores para el tono de una o varias notas de la secuencia según una relación dada con un tono determinado. Esta restricción recibe como parámetros una secuencia de notas, un rango de tonos y las posiciones de la secuencia de notas a las que se les restringirá el tono. 2. Tonos: Determina una relación directa entre el tono de cada par de notas ubicadas a n posiciones de distancia en la secuencia según una relación, un rango de notas dentro de la secuencia y un valor n dado. Los parámetros de esta restricción son: una secuencia de notas, la distancia n de las posiciones entre cada nota, un rango de posiciones entre las que se calculará la distancia, y la relación que habrá entre el tono de cada par de notas. 3. Octava: Restringe el rango de valores para la octava de una o varias notas de la secuencia según una relación dada con una octava determinada. Esta restricción recibe como parámetros una secuencia de notas, un rango de octavas y las posiciones de la secuencia de notas a las que se les restringirá la octava. 4. Octavas: Fija una relación directa entre la octava de cada par de notas ubicadas a n posiciones de distancia en la secuencia según una relación, un rango de notas dentro de la secuencia y un valor n dado. Los parámetros que recibe esta restricción son: una secuencia de notas, la distancia n de las posiciones entre cada nota, un rango de posiciones entre las que se calculará la distancia, y la relación que habrá entre la octava de cada par de notas. 5. Distancia: Establece una relación directa entre distancia en semitonos de cada par de notas ubicadas cada n posiciones en la secuencia. Esta restricción recibe como parámetros: una secuencia de notas, la distancia n de las posiciones entre cada par de notas, un rango de posiciones dentro de la secuencia, y el rango de la distancia en semitonos que habrá entre cada par de notas. 6.2.2.2 Restricciones sobre acordes 1. Tamaño: Restringe el rango del tamaño, (cantidad de notas), del acorde. Sus parámetros son un acorde y un rango indicando el tamaño del acorde; 22 MODELO E IMPLEMENTACIÓN 2. Inclusión de notas: Establece qué notas estarán dentro del acorde sin excluir las demás. Los parámetros de esta restricción son: Los parámetros de esta restricción son un acorde y una lista de notas. 3. Inclusión exclusiva: Establece qué notas conforman el acorde excluyendo todas las demás. Los parámetros de esta restricción son un acorde y una lista de notas. 4. Exclusión de notas: Determina qué notas no estarán dentro del acorde. 5. Notas del dominio: Define qué notas podrían estar dentro del acorde sin incluir ninguna de forma explícita. Los parámetros de esta restricción son un acorde y una lista de notas. 6. Distancia entre notas: Restringe la distancia δ, en términos de semitonos, entre todas las notas consecutivas que conforman el acorde según un parámetro δ dado. Esta restricción recibe como parámetro un acorde y el rango de distancia que habrá entre cada nota. 7. Triada: Define el acorde como una triada; una triada es un acorde de tres notas pertenecientes a una escala determinada; Este acorde se forma a partir de la unión de dos Intervalos de tercera pertenecientes a la escala. Los parámetros de esta restricción son: un acorde, el tono de la fundamental de la escala, el modo de la escala, (mayor o menor), y un rango de octavas en las que se definirá la triada. 23 MODELO E IMPLEMENTACIÓN 7 MUZA: DEFINICIÓN RESTRICCIONES DEL SISTEMA DE El sistema de restricciones que se definió lleva el nombre de MuZa6; en él se encapsulan todos los procedimientos sobre notas, acordes, secuencias de notas y algunas funcionalidades de presentación de resultados basados en la notación inglesa. MuZa ha sido desarrollado en su totalidad sobre el lenguaje de programación Oz, haciendo uso de las librerías que este ofrece para la programación concurrente por restricciones y el manejo de variables de dominios y conjuntos finitos. El uso de estos aspectos hace de MuZa un sistema de restricciones rico en expresividad musical, ya que la utilización de las librerías de Mozart es transparente para el usuario final quien cuenta con los procedimientos que MuZa define para la manipulación de estructuras musicales; MuZa también es fácil de extender gracias a las facilidades de Oz para el manejo de variables de conjuntos y dominios finitos. El modelo expuesto en el capítulo anterior ha sido implementado a lo largo de los módulos de MuZa, estos módulos son: Note para el manejo de notas, NoteSequence para el manejo de secuencias de notas, OldChord, para el manejo de acordes según la primera aproximación del modelo en el que un acorde es una lista de intervalos y Chord, para el manejo de acordes según el modelo que define un acorde como un conjunto de notas. Adicionalmente, MuZa cuenta con el módulo MuzaPrint encargado de soportar todas las características de representación de las estructuras musicales. 7.1 7.1.1 Variables y Dominios Notas Como se definió en el modelo, una nota es una tupla con tres atributos de dominio finito; En Oz la implementación de este modelo se hizo a través de un registro de tres atributos: tono, octava y valor. En el sistema de restricciones, para declarar una variable nota se utiliza un procedimiento en el que se define, de forma transparente para el usuario, una nota como un registro. El siguiente ejemplo muestra cómo se declara una variable de tipo nota, y cómo esta es luego MuZa: Acrónimo de “Music for Oz”. Su significado también proviene de reemplazar en la palabra Musa la letra “s” por una Z, lo que sugiere una relación con la palabra inspiración . 6 24 MODELO E IMPLEMENTACIÓN desplegada al usuario gracias a un procedimiento definido para representar las estructuras del sistema de restricciones de una forma más sencilla. local UnaNota in UnaNota= {Muza.note.decl} {Browser.browse UnaNota} end A continuación se ilustra el resultado de la ejecución del código anterior Figura 6 Una nota en MuZa En la Figura 6 se puede ver cómo a través del procedimiento Muza.note.decl se declara una variable de tipo nota que no es más que un registro de tres posiciones cuyos dominios corresponden a lo expuesto en el modelo. Bajo la representación del registro aparece una representación de la misma nota pero bajo el procedimiento Muza.muzaPrint.print, que representa la nota con la notación domTono:domOctava, donde domTono representa el dominio del atributo tono, en el ejemplo se puede apreciar que es desde C hasta B, (C…B); y domOctava representa el dominio de la octava de la nota, que en el ejemplo va desde 0 hasta 4, (0.4). 7.1.2 Secuencia de Notas Tal como lo define el modelo, una secuencia de notas se representa por medio de una lista de estructuras de tipo nota, para declarar una variable de tipo secuencia de notas es necesario indicar el tamaño que tendrá la secuencia. A continuación se expone cómo se declara una variable de secuencia de notas de tamaño 10, y cómo esta es mostrada a través de las funcionalidades de MuZa para la representación de resultados. local Secuencia in Secuencia={Muza.noteSequence.decl 10} 25 MODELO E IMPLEMENTACIÓN end {Browser.browse Secuencia} La ejecución del código anterior arroja como resultado la Figura 7 Figura 7 Una secuencia de notas en MuZa La representación visual de la secuencia de notas corresponde, como habría de esperarse, a una sucesión de variables de tipo nota cuyos tonos y octavas no se han restringido aún más allá de lo que la definición de la nota sugiere. 7.1.3 Acordes MuZa soporta los dos modelos de acordes expuestos en el capítulo anterior, el primer modelo, en el que un acorde es una lista de intervalos o conjuntos, es denominado OldChord; el segundo modelo, en el que un acorde es un conjunto de números, es denominado Chord. Los acordes de tipo OldChord fueron implementados como listas de tamaño treinta, en las cuales cada elemento es un conjunto de cardinalidad cero o dos; fue necesario limitar el tamaño de la lista a treinta para poder utilizar las variables de tipo List de Mozart. Además, se impusieron otra serie de restricciones sobre los intervalos que conforman el acorde de modo que la implementación sea lo más clara posible y no se preste para ambigüedades que entorpezcan el desempeño de las restricciones sobre el acorde. Las restricciones adicionales sobre los intervalos que conforman el acorde son: La cardinalidad de los intervalos es un número que pertenece al conjunto {0,2}. La cardinalidad de la intersección de cualquier par de intervalos que conforman el acorde es un número que pertenece al conjunto {0,1} 26 MODELO E IMPLEMENTACIÓN Cualquier par de intervalos ini e inj cumplen que ∀(i, j ) : i < j ∧ i ∈ {x : 1 ≤ i ≤ 30} ∧ j ∈ {x : 1 ≤ i ≤ 30} ini ≥ in j Esto se hace con el fin de que los intervalos con números queden siempre al principio de la lista. Cualquier par de intervalos ini e inj cumplen que: i< j∧ ∀y∀x : y = Max(ini ) ∧ x = Min(in j ) y ≤ x = true Esto se hace con el propósito de que exista un orden en los intervalos que conforman el acorde de modo que un intervalo cumple que todas sus notas, es decir los enteros que las representan, son de menor o igual valor a la nota de mayor valor del intervalo siguiente. A continuación se ilustra cómo es la sintaxis para declarar una variable de tipo OldChord. local Acorde in Acorde= {Muza.oldChord.decl} {Browser.browse Acorde} end El resultado de la ejecución del código anterior se refleja en la Figura 8 27 MODELO E IMPLEMENTACIÓN Figura 8: Un acorde según Muza.oldChord El siguiente código declara una variable de tipo Chord: local Acorde in Acorde= {Muza.chord.decl} {Browser.browse Acorde} end Como resultado de la ejecución del código anterior se despliega la Figura 9 Figura 9: Un acorde según Muza.chord Como puede apreciarse en ambos casos, MuZa despliega un acorde de forma similar a como Mozart despliega o representa un conjunto: lo hace a través de una lista que representa el límite inferior del acorde en el que se albergan las notas que están contenidas en él, una lista que representa el límite superior en el que se albergan las notas de dominio del acorde y una variable de dominios finitos que 28 MODELO E IMPLEMENTACIÓN representa la cardinalidad del conjunto, o en este caso, la cantidad de notas que contiene el acorde. La manera como se despliega la representación de un acorde es: Para acordes no determinados: {[LowerBoundList ]K[UpperBoundList ]}* ChordSize donde LowerBoundList es una lista que contiene las notas que se sabe irán en el acorde, UpperBoundList es una lista conformada por el dominio de notas del acorde, y ChordSize es la descripción del tamaño del acorde. Para acordes determinados: {Nt1 , Nt2 K Nti K Nt n }∗ n , donde Nti es uma nota del acorde y n es el número de notas que hay en el acorde. 7.2 7.2.1 7.2.1.1 Restricciones Restricciones sobre Notas Restricción de Tono: La restricción de tono se encuentra almacenada en el procedimiento Tone del módulo Note en Muza. Esta restricción recibe como parámetros: Una variable de tipo nota η Un literal, o lista de literales τ representando el tono, tal que τ ∈ {' C ' , ' C # ' , ' Db' , ' D' , ' D # ' , ' Eb' , ' E ' , ' F ' , ' F # ' , ' Gb' , ' G ' , ' G # ' , ' Ab' , ' A' , ' A# ' , ' Bb' , ' B'} Una literal ℓ que pertenece al conjunto {' =:' , ' <:' , ' =<:' , ' >:' , ' >=:' , '\\ =:' , '::'} El literal τ es una lista sólo cuando ℓ es igual a '::' , de este modo se indica que el tono de la nota puede determinar su valor dentro del conjunto de valores dados por τ. En MuZa, un ejemplo de la utilización de esta restricción que se impone sobre una variable de tipo nota nt para restringir su tono sería: {Muza.note.tone Nt ‘=:’ ‘E’} Esta instrucción impone sobre la variable Nt, (que debe ser de tipo nota), lo que se traduciría como “El tono de Nt es igual a E. 29 MODELO E IMPLEMENTACIÓN Esta restricción se encarga de eliminar del dominio del atributo tono de la nota Nt todos los valores x que no cumplan con el enunciado x ∈ {τ } Al eliminar valores del dominio del atributo tono, gracias a la restricción inicial impuesta al declarar una variable nota: vlr =: (12 × nο ) + n , el dominio del atributo valor también es podado haciendo propagación de intervalos y de espacios dentro del dominio. El efecto de la aplicación de la restricción tal como se ejemplariza se puede apreciar en la Figura 10. Figura 10 Una nota con el tono restringido 7.2.1.2 Restricción de Octava La restricción de octava se encuentra almacenada en el procedimiento Octave del módulo Note en Muza. Esta restricción recibe como parámetros: Una variable de tipo nota η Un valor, o lista de valores enteros ο entre cero y cuatro que indicará(n) el(los) posible(s) valor(es) de la octava de la nota. Una literal ℓ que pertenece al conjunto {' =:' , ' <:' , ' =<:' , ' >:' , ' >=:' , '\\ =:' , '::'} El valor ο es una lista sólo cuando ℓ es igual a '::' , de este modo se indica que la octava de la nota puede determinar su valor dentro del conjunto de valores dados por ο. 30 MODELO E IMPLEMENTACIÓN En MuZa, un ejemplo de la utilización de esta restricción que se impone sobre una variable de tipo nota nt para restringir su octava sería: {Muza.note.octave Nt ‘=:’ 0} Esta instrucción impone sobre la variable Nt, (que debe ser de tipo nota), la restricción “La octava en la que Nt se encuentra es igual a 0”. Esta restricción se encarga de eliminar del dominio del atributo octava de la nota Nt todos los valores x que no cumplan con el enunciado x ∈ {ο } Al eliminar valores del dominio del atributo octava, gracias a la restricción inicial impuesta al declarar una variable nota: vlr =: (12 × nο ) + n , el dominio del atributo valor también es podado haciendo propagación de intervalos y de espacios dentro del dominio. El efecto de la restricción sobre los dominios de los atributos de la nota se pueden observar en la Figura 11, que es el resultado de ejecutar la instrucción descrita anteriormente que restringe la octava de la nota a cero. Figura 11 Una nota con su octava restringida 7.2.1.3 Restricción sobre el tono de dos notas La restricción sobre el tono de dos notas se encuentra almacenada en el procedimiento Tones del módulo Note en MuZa. Esta restricción recibe como parámetros: Dos variables de tipo nota: η1 y η2 Un literal ℓ que pertenece al conjunto {' =:' , ' <:' , ' =<:' , ' >:' , ' >=:' , '\\ =:'} 31 MODELO E IMPLEMENTACIÓN La instrucción que impone esta restricción es: {Muza.note.tones η1 η2 ℓ} Un ejemplo de la imposición de esta restricción sobre dos variables de tipo nota se vería, según MuZa, así: local Nota1 Nota2 in Nota1={Muza.note.decl} Nota2={Muza.note.decl} {Muza.note.tones Nota1 Nota2 '<:'} % Restricción de tonos {Browser.browse ['esta es la nota1:' Nota1]} {Browser.browse ['esta es la nota2:' Nota2]} end Esta instrucción se traduce con la sentencia “El tono de Nota1 es menor que el tono de Nota2”. Internamente, esta restricción accede los atributos Tono de cada nota y les impone la restricción Nota1.tono <: Nota2.tono De este modo, los tonos de ambas notas quedan relacionados entre si de manera que al restringir más el tono de una de las notas se reflejará una poda de dominios también en el tono de la otra nota. La ejecución del código anterior produce la salida de la Figura 12, en la que se refleja el efecto de la restricción sobre los dominios de ambas variables. Figura 12: Restricción sobre el tono de dos notas 32 MODELO E IMPLEMENTACIÓN 7.2.1.4 Restricción sobre las octavas de dos notas La restricción sobre el tono de dos notas funciona de forma similar a la restricción sobre el tono de dos notas descrita anteriormente; se encuentra almacenada en el procedimiento Octaves del módulo Note en MuZa. Esta restricción tiene los siguientes parámetros: Dos variables de tipo nota: η1 y η2 Un literal ℓ que pertenece al conjunto {' =:' , ' <:' , ' =<:' , ' >:' , ' >=:' , '\\ =:'} La forma general en que se impone esta restricción sobre dos notas es: {Muza.note.octaves η1 η2 ℓ} Un ejemplo de la imposición de esta restricción sobre dos variables de tipo nota utilizando lo definido por MuZa, se vería así: {Muza.note.octaves Nota1 Nota2 ‘=:’} La anterior instrucción se traduce como “La octava de Nota1 es la misma octava de la Nota2”, es decir que ambas notas están ubicadas en la misma octava. Internamente se logra establecer esta relación accediendo a los atributos Octava de cada nota e imponiendo sobre ellos la restricción. Nota1.octava =: Nota2.octava El efecto de la aplicación de esta restricción en este ejemplo en particular sólo se reflejará cuando se restrinja el dominio de la octava de alguna de las notas, de modo que los efectos se verán sobre ambas. A continuación se muestra un ejemplo de la imposición de esta restricción. La ejecución del código descrito produce como salida lo mostrado en la Figura 13 Nota1 Nota2 Nota1={Muza.note.decl} Nota2={Muza.note.decl} {Muza.note.octaves Nota1 Nota2 '=:'} {Browser.browse ['esta es la nota1:' Nota1]} {Browser.browse ['esta es la nota2:' Nota2]} 33 MODELO E IMPLEMENTACIÓN Figura 13 Restricción sobre la octava de dos notas Hasta ahora la salida no indica cambios en los dominios de las variables, sin embargo al ejecutar la siguiente línea: {Muza.note.octave Nota1 '>:' 3} El cambio se refleja en ambas notas tal como lo muestra la Figura 14. Aunque el cambio se aprecia de inmediato en las variables de tipo Nota cuando estas son mostradas a modo de registro, para que MuzaPrint despliegue los valores actualizados de los dominios de las notas es necesario seleccionar las notas e indicarle al Browser de Mozart que aplique la función MuzaPrint sobre ellas nuevamente. Figura 14: Producto de la restricción sobre la octava de dos notas 7.2.1.5 Restricción sobre la distancia entre dos notas Como se definió en el modelo, la restricción de distancia entre dos notas fija un rango de distancia entre dos notas en términos de semitonos. Esta restricción está 34 MODELO E IMPLEMENTACIÓN albergada en el procedimiento Distance del módulo Note en MuZa. Los parámetros que recibe esta restricción son: Dos variables de tipo nota : η1 y η2 Un literal ℓ que pertenece al conjunto {' =:' , ' <:' , ' =<:' , ' >:' , ' >=:' , '\\ =:'} Un entero δ que representa la distancia en semitonos entre ambas notas. La forma para imponer esta restricción sobre dos notas es: {Muza.note.distance η1 η2 ℓ δ} Un ejemplo de la aplicación de esta restricción en dos notas sería entonces: {Muza.note.distance Nota1 Nota2 '=:' 3} Esta instrucción codifica la sentencia “entre Nota1 y Nota2 hay exactamente 3 semitonos”. Para poder apreciar el efecto de esta restricción, en este ejemplo en particular, sobre el dominio de las notas, es necesaria acompañarla con otras restricciones. local Nota1 Nota2 in Nota1={Muza.note.decl} Nota2={Muza.note.decl} {Muza.note.distance Nota1 Nota2 '=:' 3} {Muza.note.octave Nota1 '>:' 3} {Browser.browse ['esta es la nota1:' Nota1]} {Browser.browse ['esta es la nota2:' Nota2]} end La ejecución del código anterior da como resultado lo ilustrado por la Figura 15. Ahí se puede apreciar que la octava de Nota1 es cuatro, por lo tanto la octava de Nota2 se ve afectada y sólo podrá adquirir los valores tres o cuatro para respetar la restricción de distancia impuesta sobre ellas. 35 MODELO E IMPLEMENTACIÓN Figura 15: Restricción de distancia sobre dos notas donde una de ellas tiene la octava restringida 7.2.2 7.2.2.1 Restricciones sobre Secuencias de notas Restricción sobre el tono de una o varias notas en la secuencia La restricción sobre el tono de una o varias notas en la secuencia se encuentra almacenada en el procedimiento Tone del módulo NoteSequence en MuZa. Esta restricción se encarga de fijar un rango de valores para el tono de una o varias notas ubicadas en un conjunto de posiciones dadas. Los parámetros que recibe el procedimiento Tone son: Un literal ℓ que pertenece al conjunto {' =:' , ' <:' , ' =<:' , ' >:' , ' >=:' , '\\ =:' , '::'} Un valor τ válido para describir el tono de una nota, τ puede ser un tono, una lista de tonos o una tupla de la forma ti#tf donde ti y tf son tonos τ que indican un rango. Los tonos τ cumplen: τ ∈ {' C ' , ' C # ' , ' Db' , ' D' , ' D # ' , ' Eb' , ' E ' , ' F ' , ' F # ' , ' Gb' , ' G ' , ' G # ' , ' Ab' , ' A' , ' A# ' , ' Bb' , ' B'} Una secuencia de notas SeqN La variable p que indica la o las posiciones de la secuencia a las que se les restringirá el tono, p puede ser un número, una lista de números, una tupla de la forma ini#fin indicando un rango, una tupla de la forma ini#fin#paso indicando un rango y una distancia entre los valores del rango, o el literal ‘all’ que indicará todas las posiciones de la secuencia. Cuando ℓ es igual a ‘::’ entonces τ puede tomar la forma de lista o de tupla, en el resto de los casos τ debe ser un tono. La forma para imponer esta restricción es: 36 MODELO E IMPLEMENTACIÓN {Muza.noteSequence.tone ℓ τ SeqN p} Un ejemplo de la utilización de esta restricción sobre una secuencia de notas NoteSeq de tamaño 10 sería: {NoteSequence.tone '::' 'G#'#'B' NoteSeq [1 3 5 7 9]} Esta instrucción se puede leer como: “Para las posiciones 1,3,5,7 y9 de la variable NoteSeq el tono está entre G# y B”. En este ejemplo se hace uso del literal ‘::’ junto con una tupla que indica un rango de tonos. Internamente, el procedimiento Tone de NoteSequence hace uso del procedimiento Tone del módulo Note para cada una de las posiciones indicadas. El código completo para la ejecución del ejemplo anterior se muestra a continuación: local NoteSeq in NoteSeq={NoteSequence.decl 10} {NoteSequence.tone '::' 'G#'#'B' NoteSeq [1 3 5 7 9]} {Browser.browse NoteSeq} end Como resultado a la ejecución del código anterior se obtiene lo ilustrado en la Figura 16. Figura 16 Uso de la restricción Tone sobre una secuencia de notas 37 MODELO E IMPLEMENTACIÓN 7.2.2.2 Restricción sobre la octava de una o varias notas en la secuencia La restricción sobre la octava de una o varias notas ubicadas en una secuencia de notas se encuentra almacenada en el procedimiento Octave del módulo NoteSequence en MuZa. Esta restricción se encarga de fijar un rango de valores para la octava de una o varias notas ubicadas en un conjunto de posiciones dadas. Los parámetros que recibe el procedimiento Octave son: Un literal ℓ que pertenece al conjunto {' =:' , ' <:' , ' =<:' , ' >:' , ' >=:' , '\\ =:' , '::'} Un valor ο válido para describir la octava de una nota; ο puede ser un entero, una lista de enteros o una tupla de la forma oi#of donde oi y of son octavas ο entre 0 y 4 que indican un rango. Para todo valor ο se cumple: ο ∈ {0K 4} Una secuencia de notas SeqN La variable p que indica la o las posiciones de la secuencia a las que se les restringirá la octava, p puede ser un número, una lista de números, una tupla de la forma ini#fin indicando un rango, una tupla de la forma ini#fin#paso indicando un rango y una distancia entre los valores del rango o el literal ‘all’ que indicará todas las posiciones de la secuencia. Cuando ℓ es igual a ‘::’ entonces ο puede tomar la forma de lista o de tupla, en el resto de los casos ο debe ser un número. La forma para imponer esta restricción es: {Muza.noteSequence.octave ℓ ο SeqN p} Un ejemplo de la utilización de esta restricción sobre una secuencia de notas NoteSeq de tamaño 10 sería: {Muza.noteSequence.octave '::' [3 4] NoteSeq 2#5#1} Esta instrucción se puede leer como: “Desde la posición 2 hasta la 5 de la variable NoteSeq la octava será 3 o 4”. En este ejemplo se hace uso del literal ‘::’ junto con una lista que indica los posibles valores para la octava y una tupla de la forma ini#fin#paso. Internamente, el procedimiento Octave de NoteSequence hace uso del procedimiento Octave del módulo Note para cada una de las posiciones indicadas. 38 MODELO E IMPLEMENTACIÓN El código completo para la ejecución del ejemplo anterior se muestra a continuación: local NoteSeq in NoteSeq={NoteSequence.decl 10} {Muza.noteSequence.octave '::' [3 4] {Browser.browse NoteSeq} end NoteSeq 2#5#1} la ejecución del código anterior se refleja sobre la variable NoteSeq tal como lo indica la Figura 17. Figura 17: Restricción de la octava de una secuencia de notas 7.2.2.3 Restricción sobre los tonos de cada par de notas ubicadas a cierta distancia El procedimiento Tones del módulo NoteSequence en MuZa almacena la restricción que relaciona los tonos de cada par de notas ubicadas a una distancia dada, en un rango de una secuencia de notas. Los parámetros de la restricción Tones son: Un literal ℓ que pertenece al conjunto {' =:' , ' <:' , ' =<:' , ' >:' , ' >=:' , '\\ =:'} Una secuencia de notas SeqN Un entero δ indicando la distancia entre cada par de notas a las que se les relacionará el tono. Un entero posIni que indica la posición a partir de la cual se tomará el rango de la secuencia de notas. 39 MODELO E IMPLEMENTACIÓN Un entero posFin que indica la posición final del rango de la secuencia de notas. Internamente, para cada par de notas ubicadas cada δ posiciones dentro del rango indicado, el procedimiento Tones del módulo NoteSequence hace uso del procedimiento Tones del módulo Note descrito anteriormente. En general, la aplicación de la restricción Tones sobre una secuencia de notas se hace con la instrucción: {Muza.noteSequence.tones ℓ SeqN δ posIni posFin} Un ejemplo del uso de este procedimiento sobre una secuencia de notas NoteSeq de tamaño 10 sería: {Muza.noteSequence.tones '<:' NoteSeq 2 1 10} La aplicación de esta restricción sobre NoteSeq se entiende como: “Desde la posición 1 hasta la 10 de NoteSeq, el tono de cada par de notas n1 y n2 ubicadas cada 2 posiciones cumplirá la restricción n1.tono < : n2.tono ”. El código completo para la ejecución del ejemplo y el resultado del mismo (Figura 18) se muestran a continuación local NoteSeq in NoteSeq={Muza.noteSequence.decl 10} {Muza.noteSequence.tones '<:' NoteSeq 2 1 10} {Browser.browse NoteSeq} end 40 MODELO E IMPLEMENTACIÓN Figura 18: Aplicación de la restricción Tones sobre una secuencia de notas Como puede apreciarse en la Figura 18, la poda de dominios obedece al efecto de la restricción Tones del módulo Note aplicada sobre cada par de notas ubicadas cada dos posiciones. 7.2.2.4 Restricción sobre las octavas de cada par de notas ubicadas a cierta distancia La restricción que relaciona las octavas de cada par de notas ubicadas a una distancia dada, en un rango de una secuencia de notas está almacenada en el procedimiento Octaves del módulo NoteSequence en MuZa. Los parámetros de la restricción Octaves son: Un literal ℓ que pertenece al conjunto {' =:' , ' <:' , ' =<:' , ' >:' , ' >=:' , '\\ =:'} Una secuencia de notas SeqN Un entero δ indicando la distancia entre cada par de notas a las que se les relacionará la octava. Un entero posIni que indica la posición a partir de la cual se tomará el rango de la secuencia de notas. Un entero posFin que indica la posición final del rango de la secuencia de notas. El procedimiento Octaves del módulo NoteSequence hace uso de la restricción Octaves del módulo Note para cada par de notas ubicadas cada δ posiciones dentro 41 MODELO E IMPLEMENTACIÓN del rango indicado. En general, la aplicación de la restricción Octaves sobre una secuencia de notas se hace con la instrucción: {Muza.noteSequence.octaves ℓ SeqN δ posIni posFin} Un ejemplo del uso de este procedimiento sobre una secuencia de notas NoteSeq de tamaño 10 sería: {Muza.noteSequence.octaves '>:' NoteSeq 2 1 10} La aplicación de esta restricción sobre NoteSeq se entiende como: “Desde la posición 1 hasta la 10 de NoteSeq, la octava de cada par de notas n1 y n2 ubicadas cada 2 posiciones cumplirá la restricción n1.octava >: n2.octava”. Para observar cómo este procedimiento poda los dominios de las notas en una secuencia de notas se ejecuta el siguiente código, cuyo resultado se ilustra en la Figura 19. local NoteSeq in NoteSeq={Muza.noteSequence.decl 10} {Muza.noteSequence.octaves '>:' NoteSeq 2 1 10} {Browser.browse NoteSeq} end Figura 19: Poda de dominios sobre una secuencia de notas por la restricción Octaves 7.2.2.5 Restricción sobre la distancia de cada par de notas ubicadas a cierta distancia La restricción que relaciona la distancia, en términos de semitonos, de cada par de notas ubicadas a una cantidad de posiciones dada en un rango de una secuencia 42 MODELO E IMPLEMENTACIÓN de notas está almacenada en el procedimiento Distance del módulo NoteSequence en MuZa. Los parámetros de la restricción de distancia sobre una secuencia de notas son: Un literal ℓ que pertenece al conjunto {' =:' , ' <:' , ' =<:' , ' >:' , ' >=:' , '\\ =:'} Una secuencia de notas SeqN Un entero δ indicando la distancia en semitonos para cada par de notas. Un entero numPos indicando la cantidad de posiciones que habrá entre cada par de notas del rango sobre las que se aplicará la restricción. Un entero posIni que indica la posición a partir de la cual se tomará el rango de la secuencia de notas. Un entero posFin que indica la posición final del rango de la secuencia de notas. El procedimiento Distance del módulo NoteSequence hace uso de la restricción Distance del módulo Note para todo par de notas ubicadas cada numPos posiciones dentro del rango indicado. En general, la aplicación de la restricción Distance sobre una secuencia de notas se hace con la instrucción: {Muza.noteSequence.distance ℓ δ SeqN numPos posIni posFin} Un ejemplo del uso de este procedimiento sobre una secuencia de notas NoteSeq de tamaño 10 sería: {Muza.noteSequence.distance '=:' 4 NoteSeq 2 1 10} La aplicación de esta restricción sobre NoteSeq se entiende como: “Desde la posición 1 hasta la 10 de NoteSeq, cada par de notas n1 y n2 ubicadas cada 2 posiciones tendrán 4 semitonos de distancia entre ellas”. Para observar cómo este procedimiento obra sobre los dominios de las notas en una secuencia, hace falta aplicar otra restricción sobre una de notas de la secuencia, ya que la restricción de distancia por si sola no hará poda de dominios de inmediato. El siguiente código combina la restricción de octava sobre una 43 MODELO E IMPLEMENTACIÓN secuencia de notas con la restricción de distancia, la poda de dominios sobre las demás notas de la secuencia es hecha por la restricción de distancia gracias a la información dada por la restricción de octava a la primer nota de la secuencia. El resultado de la ejecución del código se muestra en la Figura 20 local NoteSeq in NoteSeq={Muza.noteSequence.decl 10} {Muza.noteSequence.distance '=:' 4 NoteSeq 2 1 10} {Muza.noteSequence.octave '=:' 2 NoteSeq 1} {Browser.browse NoteSeq} end Figura 20: Poda de dominios hecha por la restricción de distancia en una Secuencia de notas 7.2.3 7.2.3.1 Restricciones sobre Acordes Restricción sobre el tamaño de un acorde La restricción sobre el número de notas que contiene un acorde está implementada dentro del procedimiento Size de los módulos Chord y OldChord de MuZa. Los parámetros que recibe el procedimiento Size en ambos módulos son: Un acorde Ch Un literal ℓ que pertenece al conjunto {' =:' , ' <:' , ' =<:' , ' >:' , ' >=:' , '\\ =:'} Un entero n para indicar el tamaño del acorde. La restricción de tamaño se impone sobre una variable de tipo acorde, y según el modelo utilizado para definir el acorde se utiliza una de las siguientes líneas: {Muza.chord.size Ch ℓ n} 44 MODELO E IMPLEMENTACIÓN {Muza.oldChord.size Ch ℓ n} 7.2.3.1.1 Funcionamiento de Chord.size La restricción del tamaño del acorde cuando este es definido como un conjunto se traduce en una restricción sobre la cardinalidad del mismo. Para restringir la cardinalidad de un conjunto, el módulo FS, (Finite Sets), de Mozart contiene el procedimiento CardRange que recibe dos enteros I1 e I2 y una variable de tipo conjunto. CardRange básicamente indica que la cardinalidad del conjunto se encuentra en el rango [I1 , I2]; FS también cuenta con el procedimiento Card que retorna el valor correspondiente a la cardinalidad de un conjunto. El uso que se le da a CardRange para restringir el tamaño de un acorde va directamente ligado al literal ℓ pasado como parámetro; la diferencia en el uso de la función CardRange según el literal se observa en la Tabla 3. Literal ‘=:’ ‘>:’ ‘>=:’ ‘=<:’ ‘<:’ ‘\\=:’ Uso de CardRange {FS.cardRange N N Chord} {FS.cardRange N+1 60 Chord} {FS.cardRange N 60 Chord} {FS.cardRange 3 N Chord} {FS.cardRange 3 N-1 Chord} Tamano \=: N {FS.card Chord Tamano} Tabla 3: Restricción del tamaño de un conjunto según un literal dado La poda de dominios hecha por la restricción de tamaño sobre un acorde se ilustra en la Figura 21 tras el resultado de ejecutar la siguiente porción de código: local Ch in {Muza.chord.decl Ch} {Muza.chord.size Ch '<:' 4} {Browser.browse Ch} end La Figura 21 está seccionada en dos partes, ya que como el acorde tiene dentro de su límite superior todas las notas del dominio no se alcanza a ver el final de la línea en una sola pantalla. La figura muestra las secciones inicial y final de la misma línea tras ejecutar el código anterior. 45 MODELO E IMPLEMENTACIÓN Figura 21 Efecto de la restricción de tamaño sobre un acorde de tipo Chord 7.2.3.1.2 Funcionamiento de OldChord.size La restricción del tamaño del acorde, cuando este es definido como una lista de conjuntos, se traduce en la restricción de la cardinalidad del conjunto unión de todos los elementos de la lista Ch. Size = U in in∈Ch Entonces, el uso de la restricción CardRange es el mismo para los acordes de la forma OldChord que para los acordes de la forma Chord, siendo la única diferencia el conjunto al cual se le aplica la restricción; en este caso, la restricción a la cardinalidad se le hace al conjunto unión, mientras que en el anterior se hacía directamente sobre el acorde dado que el miso es un conjunto. Lo anterior indica que la Tabla 3 también sirve para describir el uso de la restricción CardRange sobre los acordes de la forma OldChord. Adicional a la restricción CardRange, hay unas consideraciones a tener en cuenta según el literal recibido por el procedimiento. Estas consideraciones van ligadas a la definición de los intervalos contenidos en la lista que forma el acorde y las restricciones impuestas sobre ellos. Las consideraciones según el literal recibido y un tamaño n dado son: ‘=:’ La cantidad máxima de intervalos que describen un acorde de tamaño n es n-1, por lo tanto los intervalos ubicados a partir de la posición n tendrán cardinalidad igual a cero. ‘>:’ La cantidad mínima de intervalos, (minInter), que describen un acorde cuyo tamaño es mayor que n es: n/2 +1 si n es par , o n 2 si n es impar. Por 46 MODELO E IMPLEMENTACIÓN lo tanto desde la primera posición de la lista hasta minInter la cardinalidad de los intervalos es igual a dos. ‘>=:’ La cantidad mínima de intervalos, (minInter), que describen un acorde cuyo tamaño es mayor o igual que n es: n/2 si n es par , o n 2 si n es impar. Por lo tanto desde la primera posición de la lista hasta minInter la cardinalidad de los intervalos es igual a dos. ‘<:’ La cantidad máxima de intervalos que describen un acorde de tamaño menor que n es n-2, por lo tanto los intervalos ubicados a partir de la posición n-1 tendrán cardinalidad igual a cero. ‘=<:’ La cantidad máxima de intervalos que describen un acorde de tamaño menor o igual que n es n-1, , por lo tanto los intervalos ubicados a partir de la posición n tendrán cardinalidad igual a cero. La poda de dominios sobre un acorde al que se le ha aplicado la restricción de tamaño se ilustra en la , y es el resultado de ejecutar la siguiente porción de código: local Ch in {Muza.oldChord.decl Ch} {Muza.oldChord.size Ch '<:' 4} {Browser.browse Ch} end Figura 22: Efecto de la restricción de tamaño sobre un acorde de tipo OldChord 7.2.3.2 Restricción de Inclusión de notas en un Acorde 47 MODELO E IMPLEMENTACIÓN La restricción sobre las notas que se incluyen en un acorde está implementada dentro del procedimiento Include de los módulos Chord y OldChord de MuZa. Los parámetros que recibe el procedimiento Include en ambos módulos son: Un acorde Ch. Una representación válida de notas n, donde n puede ser una nota o una lista de notas. La restricción de inclusión de notas se impone sobre una variable de tipo acorde, y según el modelo utilizado para definir el acorde se utiliza una de las siguientes líneas: {Muza.chord.include n Ch } {Muza.oldChord.include n Ch} 7.2.3.2.1 Funcionamiento de Chord.include La restricción de inclusión de notas en un acorde es expresada por medio de la restricción include del módulo FS de Mozart que sirve para incluir valores determinados en un conjunto finito. Cuando el acorde ha sido definido como un conjunto de valores que representan notas, la restricción FS.include es impuesta sobre el acorde como tal, y su aplicación se refleja sobre el dominio del acorde agregando el (los) valor(es) incluido(s) al acorde en la lista del límite inferior del acorde. La poda de dominios que realiza esta restricción sobre un acorde se puede observar tras la ejecución del siguiente código en la Figura 23. local Ch Notas N1 N2 N3 in {Muza.chord.decl Ch} {Muza.note.decl N1} {Muza.note.decl N2} {Muza.note.decl N3} {Muza.note.tone N1 '=:' 'C'} {Muza.note.tone N2 '=:' 'D'} {Muza.note.tone N3 '=:' 'G'} {Muza.note.octave N1 '=:' 0} {Muza.note.octave N2 '=:' 0} {Muza.note.octave N3 '=:' 0} Notas=[N1 N2 N3] 48 MODELO E IMPLEMENTACIÓN end {Muza.chord.include Notas Ch} {Browser.browse Ch} Figura 23: Poda de dominios de un acorde tras incluir notas en él 7.2.3.2.2 Funcionamiento de OldChord.include Cuando el acorde ha sido definido como una lista de conjuntos que representan intervalos de notas, a restricción de inclusión de notas impone la restricción FS.include sobre el conjunto unión de la lista de intervalos. Como la restricción es impuesta sobre el conjunto unión y no sobre un intervalo en particular, entonces no se refleja de inmediato sobre los dominios del acorde, sin embargo, si se impusieran más restricciones sobre el acorde se apreciaría que la inclusión de las notas si se llevó a cabo. La ejecución del siguiente fragmento de código ilustra cómo se utiliza el procedimiento include. Los resultados obtenidos se despliegan en la Figura 24. local Ch Notas N1 N2 N3 in {Muza.oldChord.decl Ch} {Muza.note.decl N1} {Muza.note.decl N2} {Muza.note.decl N3} {Muza.note.tone N1 '=:' 'C'} {Muza.note.tone N2 '=:' 'D'} {Muza.note.tone N3 '=:' 'G'} {Muza.note.octave N1 '=:' 0} {Muza.note.octave N2 '=:' 0} {Muza.note.octave N3 '=:' 0} 49 MODELO E IMPLEMENTACIÓN end Notas=[N1 N2 N3] {Muza.oldChord.include Notas Ch} {Browser.browse Ch} Figura 24: Acorde del tipo OldChord al que se le ha incluido una lista de notas 7.2.3.3 Restricción de Inclusión exclusiva de notas en un acorde La restricción sobre las notas que se incluyen en un acorde excluyendo todas las demás está implementada dentro del procedimiento NotesIn de los módulos Chord y OldChord de MuZa. Los parámetros que recibe el procedimiento NotesIn en ambos módulos son: Un acorde Ch. Una representación válida de notas n, donde n puede ser una nota o una lista de notas. 50 MODELO E IMPLEMENTACIÓN La restricción de inclusión exclusiva de notas se impone sobre una variable de tipo acorde, y según el modelo utilizado para definir el acorde se utiliza una de las siguientes líneas: {Muza.chord.notesIn n Ch} {Muza.oldChord.notesIn n Ch} Esta restricción hace uso de dos restricciones particulares del módulo FS de Mozart: include y exclude. El funcionamiento del procedimiento NotesIn tiene dos etapas: la inclusión de las notas dadas y la exclusión en el acorde de todas las demás notas. La inclusión de las notas dadas en el acorde se efectúa del mismo modo que en el procedimiento include descrito anteriormente. La exclusión en el acorde de todas las demás notas se lleva a cabo haciendo uso del procedimiento FS.exclude en el acorde como tal cuando este ha sido declarado como un conjunto de valores, o sobre cada uno de los intervalos que conforman la lista de intervalos del acorde si este ha sido definido como una lista de conjuntos. 7.2.3.3.1 Funcionamiento de Chord.notesIn Inmediatamente después de realizar la inclusión de las notas en el acorde es necesario saber cual es el complemento del conjunto que contiene las notas dadas, y de este modo excluir del acorde cada uno de los elementos del mismo. El cálculo del complemento del conjunto que contiene las notas dadas se hace gracias a otro procedimiento del módulo FS: compl; que se encarga de calcular el complemento de un conjunto dado. Internamente el llamado a complIn se hace de modo que retorne el conjunto de valores que no pertenecen a las notas dadas y que son menores o iguales a 59, que es el límite superior del rango de valores para representar notas en MuZa. Al calcular el conjunto complemento se procede a excluir cada una de sus notas del conjunto que representa al acorde. Los efectos sobre el dominio de un acorde al ejecutar la siguiente porción de código se reflejan en la Figura 25 local Ch Notas N1 N2 N3 in {Muza.chord.decl Ch} {Muza.note.decl N1} {Muza.note.decl N2} {Muza.note.decl N3} {Muza.note.tone N1 '=:' 'C'} {Muza.note.tone N2 '=:' 'D'} 51 MODELO E IMPLEMENTACIÓN end {Muza.note.tone N3 '=:' 'G'} {Muza.note.octave N1 '=:' 0} {Muza.note.octave N2 '=:' 0} {Muza.note.octave N3 '=:' 0} Notas=[N1 N2 N3] {Muza.chord.notesIn Notas Ch} {Browser.browse Ch} Figura 25 Acorde determinado por la restricción Chord.notesIn 7.2.3.3.2 Funcionamiento de OldChord.notesIn El funcionamiento del procedimiento notesIn en el módulo OldChord sigue el mismo orden de ideas que en el módulo Chord, que fue explicado anteriormente. La diferencia radica en los conjuntos sobre los cuales se aplican las restricciones include, exclude y compl, ya que en este caso se hace en el conjunto producto de la unión de todos los intervalos que conforman la lista que define al acorde. A diferencia del procedimiento notesIn del módulo Chord, en el módulo OldChord este procedimiento no hace poda de dominios de una forma tan significativa como se esperaría; esta situación obedece a que las restricciones aplicadas sobre el acorde resultan en restricciones aplicadas sobre el conjunto unión de todos los intervalos que definen al acorde. La ejecución del siguiente fragmento de código resulta en lo mostrado en la Figura 26. local Ch Notas N1 N2 N3 in {Muza.oldChord.decl Ch} {Muza.note.decl N1} 52 MODELO E IMPLEMENTACIÓN end {Muza.note.decl N2} {Muza.note.decl N3} {Muza.note.tone N1 '=:' 'C'} {Muza.note.tone N2 '=:' 'D'} {Muza.note.tone N3 '=:' 'G'} {Muza.note.octave N1 '=:' 0} {Muza.note.octave N2 '=:' 0} {Muza.note.octave N3 '=:' 0} Notas=[N1 N2 N3] {Muza.oldChord.notesIn Notas Ch} {Browser.browse Ch} Figura 26: Acorde restringido por el procedimiento OldChord.notesIn Como pude observarse, el comportamiento de OldChord.notesIn difiere mucho del comportamiento de Chord.notesIn, la eficiencia del modelo que implementa el módulo Chord empieza a hacerse evidente en la observación del comportamiento de esta restricción. 7.2.3.4 Restricción de exclusión de notas en un Acorde La restricción sobre las notas que se excluyen en un acorde está implementada dentro del procedimiento notesOut de los módulos Chord y OldChord de MuZa. Los parámetros que recibe el procedimiento notesOut en ambos módulos son: Un acorde Ch. 53 MODELO E IMPLEMENTACIÓN Una representación válida de notas n, donde n puede ser una nota o una lista de notas. La restricción de exclusión de notas se impone sobre una variable de tipo acorde, y según el modelo utilizado para definir el acorde se utiliza una de las siguientes líneas: {Muza.chord.notesOut n Ch } {Muza.oldChord.notesOut n Ch} 7.2.3.4.1 Funcionamiento de Chord.notesOut La restricción de exclusión de notas en un acorde es expresada por medio de la restricción exclude del módulo FS de Mozart que sirve para excluir valores determinados en un conjunto finito. Cuando el acorde ha sido definido como un conjunto de valores que representan notas, la restricción FS.exclude es impuesta sobre el acorde como tal, y su aplicación se refleja sobre el dominio del acorde eliminando el (los) valor(es) excluidos(s) al acorde en la lista del límite superior del acorde. La poda de dominios que realiza esta restricción sobre un acorde se puede observar tras la ejecución del siguiente código , tal como se despliega en la .Figura 27. local Ch Notas N1 N2 N3 in {Muza.chord.decl Ch} {Muza.note.decl N1} {Muza.note.decl N2} {Muza.note.decl N3} {Muza.note.tone N1 '=:' 'C'} {Muza.note.tone N2 '=:' 'D'} {Muza.note.tone N3 '=:' 'G'} {Muza.note.octave N1 '=:' 0} {Muza.note.octave N2 '=:' 0} {Muza.note.octave N3 '=:' 0} Notas=[N1 N2 N3] {Muza.chord.notesOut Notas Ch} {Browser.browse Ch} end 54 MODELO E IMPLEMENTACIÓN Figura 27: Exclusión de notas en un acorde de tipo Chord 7.2.3.4.2 Funcionamiento de OldChord.notesOut Cuando el acorde ha sido definido como una lista de conjuntos que representan intervalos de notas, a restricción de exclusión de notas impone la restricción FS.exclude sobre el conjunto unión de la lista de intervalos y sobre cada intervalo de la lista. La ejecución del siguiente fragmento de código ilustra cómo se utiliza el procedimiento notesOut. Los resultados obtenidos se despliegan en la Figura 28, y lo desplegado por MuzaPrint en cuanto a la representación del acorde coincide exactamente con lo representado cuando el acorde es de tipo Chord, como se mostró en el ejemplo anterior. local Ch Notas N1 N2 N3 in {Muza.oldChord.decl Ch} {Muza.note.decl N1} {Muza.note.decl N2} {Muza.note.decl N3} {Muza.note.tone N1 '=:' 'C'} {Muza.note.tone N2 '=:' 'D'} {Muza.note.tone N3 '=:' 'G'} {Muza.note.octave N1 '=:' 0} {Muza.note.octave N2 '=:' 0} {Muza.note.octave N3 '=:' 0} Notas=[N1 N2 N3] {Muza.oldChord.notesOut Notas Ch} {Browser.browse Ch} end 55 MODELO E IMPLEMENTACIÓN Figura 28: Exclusión de notas de un acorde de tipo OldChord 7.2.3.5 Restricción sobre el dominio del acorde La restricción sobre el dominio de un acorde está implementada dentro del procedimiento setDomain de los módulos Chord y OldChord de MuZa. Los parámetros que recibe el procedimiento setDomain en ambos módulos son: Un acorde Ch. Una representación válida de notas n, donde n puede ser una nota o una lista de notas. El dominio del acorde se determinará según el dominio de la(s) nota(s) pasada(s) como parámetro de la restricción en el momento en el que esta es aplicada sobre un acorde. La restricción de dominio se impone sobre una variable de tipo acorde, y según el modelo utilizado para definir el acorde se utiliza una de las siguientes líneas: 56 MODELO E IMPLEMENTACIÓN {Muza.chord.setDomain n Ch } {Muza.oldChord.setDomain n Ch} 7.2.3.5.1 Funcionamiento de Chord.setDomain Para determinar el dominio de un acorde cuando este es visto como un conjunto, en Mozart es necesario determinar su límite superior, que contiene los valores que podrán incluirse dentro del conjunto, en otras palabras el dominio del conjunto. Para lograr esto se hace uso de las distintas facilidades que ofrece el módulo FS para la manipulación de conjuntos y la creación de variables de tipo conjunto a partir de un dominio, (límite superior), dado. Internamente, Muza hace uso del procedimiento FS.var.upperBound, que declara una variable de tipo conjunto a partir de su límite superior o dominio; este procedimiento se llama indicando como límite superior el dominio de la(s) nota(s) dada(s) como parámetro de modo que se crea una variable de tipo conjunto con el dominio especificado, finalmente se indica que el conjunto o acorde pasado como parámetro debe ser igual al conjunto que se creó a partir del dominio dado. A continuación se ilustra con un ejemplo la utilización del procedimiento Chord.setDomain. La Figura 29 es el resultado de la ejecución de la siguiente porción de código: local Ch Notas N1 N2 N3 in {Muza.chord.decl Ch} {Muza.note.decl N1} {Muza.note.decl N2} {Muza.note.decl N3} {Muza.note.tone N1 '=:' 'C'} {Muza.note.tone N2 '=:' 'D'} {Muza.note.tone N3 '=:' 'G'} {Muza.note.octave N2 '=:' 0} {Muza.note.octave N3 '=:' 0} Notas=[N1 N2 N3] {Muza.chord.setDomain Notas Ch} {Browser.browse Ch} end 57 MODELO E IMPLEMENTACIÓN Figura 29: Acorde de tipo Chord al que se le asignó un dominio Como lo ilustra el ejemplo anterior en el que una de las notas del dominio no estaba determinada, setDomain toma el dominio actual de las notas que recibe como parámetro para especificar el dominio del acorde. 7.2.3.5.2 Funcionamiento de OldChord.setDomain El dominio de un acorde de tipo OldChord se establece de forma similar que el de uno de tipo Chord. La diferencia radica en que cuando el acorde es una lista de conjuntos, se debe igualar cada conjunto de la lista con un conjunto declarado a partir del dominio de la(s) nota(s) dada(s) como parámetro. El resultado de la ejecución del siguiente código se refleja en la Figura 30. local Ch Notas N1 N2 N3 in {Muza.oldChord.decl Ch} {Muza.note.decl N1} {Muza.note.decl N2} {Muza.note.decl N3} {Muza.note.tone N1 '=:' 'C'} {Muza.note.tone N2 '=:' 'D'} {Muza.note.tone N3 '=:' 'G'} {Muza.note.octave N2 '=:' 0} {Muza.note.octave N3 '=:' 0} Notas=[N1 N2 N3] {Muza.oldChord.setDomain Notas Ch} {Browser.browse Notas} {Browser.browse Ch} end 58 MODELO E IMPLEMENTACIÓN Figura 30: Acorde de tipo OldChord al que se le asignó un dominio 7.2.3.6 Restricción de distancia entre las notas de un Acorde Esta restricción se encarga de establecer una distancia, en términos de semitonos, entre cada par de notas consecutivas de un acorde. El procedimiento NotesDistance de los módulos Chord y OldChord contiene la definición de esta restricción para los dos tipos de acordes estudiados; en ambos casos los parámetros que recibe el procedimiento NotesDistance son: Un acorde Ch Un literal ℓ que pertenece al conjunto {' =:' , ' <:' , ' =<:' , ' >:' , ' >=:' , '\\ =:'} Un entero δ que representa la distancia en semitonos entre cada par de notas consecutivas del acorde. 59 MODELO E IMPLEMENTACIÓN La restricción de distancia entre notas se impone sobre un Acorde, y según el modelo con el que el acorde haya sido definido se utiliza una de las siguientes líneas: {Muza.chord.notesDistance Ch ℓ δ } {Muza.oldChord.notesDistance Ch ℓ δ } La restricción de distancia entre cada par de notas consecutivas de un acorde se encarga de realizar dos tareas fundamentales sobre el conjunto que define al acorde, ya sea el mismo acorde en el caso de estar definido como Chord, o el conjunto unión de todos los intervalos que conforman el acorde en caso de estar definido como OldChord: 1. Podar el dominio de UpperBound, (límite superior del conjunto o dominio del mismo), bajo la siguiente restricción: ∀x(x ∈ UpperBound ∧ ¬∃y ( y ∈ UpperBoud ∧ x − y lδ ) → UpperBound = UpperBound − x 2. Velar que siempre se cumpla que: ∀xy (x ∈ LowerBound ∧ y ∈ LowerBound → x − y lδ ) Donde LowerBound es el límite inferior del acorde. Cuando la restricción del numeral dos no se cumple dentro del espacio de restricciones definidas sobre el acorde, entonces el procedimiento NotesDistance hace que el espacio falle. Esta situación hace que la restricción de distancia entre las notas de un acorde haga propagación de restricciones, en el caso del numeral uno, y distribución del espacio de restricciones, en el caso del numeral dos. Estas dos tareas se llevan a cabo gracias a las facilidades que ofrece Mozart para observar el estado de una variable en el tiempo haciendo una reflexión sobre su dominio, y a las bondades del lenguaje en cuanto al manejo de hilos concurrentes bajo el lema “Concurrency for free” [27]. Aunque para ambos modelos de definición de acordes el procedimiento NotesDistance funciona bajo el mismo principio, el Conjunto sobre el cual se observan los límites inferior y superior, (lowerBound y UpperBound), cambian, por lo tanto a continuación se hace la distinción entre ambos modelos sobre el funcionamiento y resultados. Para observar el efecto de la restricción NotesDistance sobre un acorde aplicando los dos principios de propagación y distribución, es necesario indicar una estrategia de distribución y ver los 60 MODELO E IMPLEMENTACIÓN resultados en el árbol de busqueda, las estrategias de distribución para acordes deben estar definidas para conjuntos. 7.2.3.6.1 Funcionamiento de Chord.notesDistance El siguiente ejemplo hace uso de la restricción de distancia sobre un acorde junto con otras restricciones, ya que por si sola la restricción de distancia no arrojaría un espacio estable en el que un acorde pudiera determinarse. {Explorer.all proc {$ Acorde} Notas={Muza.note.getScale 'C' major 1} in Acorde = {Muza.chord.decl} {Muza.chord.size Acorde '=:' 3} {Muza.chord.setDomain Notas Acorde} {Muza.chord.notesDistance Acorde '=:'2} {FS.distribute naive [Acorde]} end } En el ejemplo anterior se hace uso del procedimiento getScale del módulo Note en MuZa, este procedimiento no impone ninguna restricción, pero es útil para retornar las notas que conforman una escala diatónica, mayor o menor, en una octava o conjunto de octavas dada. Como se puede apreciar en la Figura 31, para un acorde de tipo Chord la ejecución del código anterior toma un tiempo de 0 milisegundos en el que el árbol de profundidad 7 tiene tres nodos solución y 20 nodos fallidos. La Figura 32 despliega los resultados correspondientes a los tres nodos solución encontrados. 61 MODELO E IMPLEMENTACIÓN Figura 31: Árbol de búsqueda al aplicar la restricción de distancia sobre un acorde de tipo Chord Figura 32: Nodos solución del árbol de búsqueda de la restricción NotesDistance para un acorde de tipo Chord 7.2.3.6.2 Funcionamiento de OldChord.notesDistance A continuación se expondrá el mismo ejemplo que se efectuó sobre un acorde de tipo Chord, con el propósito de observar también la diferencia en tiempos de ejecución en ambos modelos. 62 MODELO E IMPLEMENTACIÓN {Explorer.all proc {$ Acorde} Notas={Muza.note.getScale 'C' major 1} in Acorde = {Muza.oldChord.decl} {Muza.oldChord.size Acorde '=:' 3} {Muza. oldChord.setDomain Notas Acorde} {Muza. oldChord.notesDistance Acorde '=:'2} {FS.distribute naive Acorde} end } Como se puede apreciar en la Figura 33, para un acorde de tipo OldChord la ejecución del código anterior toma un tiempo de 31 milisegundos en el que el árbol de profundidad 8 tiene tres nodos solución y 28 nodos fallidos. La Figura 34 despliega los resultados correspondientes a los tres nodos solución encontrados. Figura 33: Árbol de búsqueda al aplicar la restricción de distancia sobre un acorde de tipo OldChord 63 MODELO E IMPLEMENTACIÓN Figura 34: Nodos solución del árbol de búsqueda de la restricción NotesDistance para un acorde de tipo OldChord De este modo, se observa cómo el modelo representado por el módulo Chord es mucho más eficiente en cuanto a los cálculos que sobre él se realizan al utilizar las restricciones definidas, esto se debe a que es mucho más sencillo manejar un conjunto restringiendo su dominio, cardinalidad y demás atributos que manejar una lista de conjuntos para restringir el conjunto producto de la unión de los mismos y los atributos de éste. 7.2.3.7 Restricción Triada La restricción Triad aplicada sobre un acorde lo define como una triada; esta restricción se encuentra implementada para los módulos Chord y OldChord. En ambos casos los parámetros de entrada del procedimiento Triad son: Un literal key, indicando la clave o primer grado de la escala diatónica en la que la triada estará inmersa. tal que: key ∈ {' C ' , ' C # ' , ' Db' , ' D' , ' D # ' , ' Eb' , ' E ' , ' F ' , ' F # ' , ' Gb' , ' G ' , ' G # ' , ' Ab' , ' A' , ' A# ' , ' Bb' , ' B '} Un literal mod, que representa el modo de la escala. mod pertenece al conjunto {major, minor} Una variable octDom, tal que octDom puede ser el átomo all, un número o una lista de números entre cero y cuatro Un acorde Ch que será restringido como una triada. La restricción triada se impone sobre una variable de tipo acorde según el modelo utilizado para definirla haciendo uso de alguna de las líneas siguientes: 64 MODELO E IMPLEMENTACIÓN {Muza.chord.triad key mod OctDom Ch} {Muza.oldChord.triad key mod OctDom Ch} La restricción triada, a semejanza con la restricción de distancia entre las notas de un acorde, se encarga de realizar dos tareas fundamentales sobre el conjunto que define al acorde, ya sea el mismo acorde en el caso de estar definido como Chord, o el conjunto unión de todos los intervalos que conforman el acorde en caso de estar definido como OldChord: 1. Podar el dominio de UpperBound, (límite superior del conjunto o dominio del mismo), bajo la siguiente restricción: ∀x(x ∈ UpperBound ∧ x ∉ valsScale(key, mod,OctDom)) → UpperBound = UpperBound − x Donde valsScale(key, mod, OctDom) es el conjunto de valores que representan notas pertenecientes a la escala diatónica de modo mod cuyo primer grado es key y que están en la(s) octava(s) definida(s) por OctDom. 2. Velar que siempre se cumpla que: ∀x∃y (x ∈ LowerBound ∧ y ∈ LowerBound → forman _ IntervaloT ercera ( x, y ) Donde LowerBound es el límite inferior del acorde y forman_IntervaloTercera(x,y) es una función que determina si x e y forman un intervalo de tercera, que es necesario para que el acorde sea una triada. Cuando la restricción del numeral dos no se cumple dentro del espacio de restricciones definidas sobre el acorde, entonces el procedimiento Tirad hace que el espacio falle. Esta situación hace que la restricción triada haga propagación de restricciones, en el caso del numeral uno, y distribución del espacio de restricciones, en el caso del numeral dos. Estas dos tareas se llevan a cabo gracias a las facilidades que ofrece Mozart para observar el estado de una variable en el tiempo haciendo una reflexión sobre su dominio, y a las bondades del lenguaje en cuanto al manejo de hilos concurrentes bajo el lema “Concurrency for free” [27]. Aunque para ambos modelos de definición de acordes el procedimiento Triad funciona bajo el mismo principio, el Conjunto sobre el cual se observan los límites inferior y superior, (lowerBound y UpperBound), cambian, por lo tanto a continuación se hace la distinción entre ambos modelos sobre el funcionamiento y resultados. Para observar el efecto de la restricción Triad sobre un acorde aplicando los dos principios de propagación y distribución, es necesario indicar 65 MODELO E IMPLEMENTACIÓN una estrategia de distribución y ver los resultados en el árbol de búsqueda, las estrategias de distribución para acordes deben estar definidas para conjuntos. 7.2.3.7.1 Funcionamiento de Chord.triad El siguiente ejemplo hace uso de la restricción triada, y distribuye el espacio de búsqueda para encontrar las distintas soluciones. {Explorer.all proc{$Triada} Triada={Muza.chord.decl} {Muza.chord.triad 'C' major 0 Triada} {FS.distribute naive [Triada]} end} Como lo muestra la Figura 35, la ejecución del código anterior toma 15 milisegundos, tiempo en el cual el árbol de búsqueda de profundidad 7 tiene cinco nodos solución y 16 nodos fallidos. La Figura 36 despliega los resultados correspondientes a los nodos solución encontrados. Figura 35: Árbol de búsqueda para una triada de tipo Chord en do mayor ubicada en la octava 0 66 MODELO E IMPLEMENTACIÓN Figura 36: Nodos solución del árbol de búsqueda de la restricción Triad para un acorde de tipo Chord 7.2.3.7.2 Funcionamiento de OldChord.triad El siguiente ejemplo, al igual que el anterior, hace uso de la restricción triada para encontrar las triadas existentes en la escala de do mayor ubicada en la octava cero, y distribuye el espacio de búsqueda para encontrar las distintas soluciones. {Explorer.all proc{$Triada} Triada={Muza.oldChord.decl} {Muza. oldChord.triad 'C' major 0 {FS.distribute naive Triada} end} Triada} Como lo indica la Figura 37, el código anterior toma un tiempo de 32 milisegundos para ejecutarse y produce un árbol de búsqueda de profundidad 8 con cinco soluciones y 22 nodos fallidos. En la Figura 38 se despliegan los resultados correspondientes al árbol de búsqueda. Nuevamente, se evidencia que el módulo Chord, que implementa el modelo de acorde como conjunto de valores que representan notas, es más eficiente en el manejo de sus atributos y en la aplicación de las restricciones que el modelo que implementa un acorde como una lista de intervalos en el módulo OldChord. 67 MODELO E IMPLEMENTACIÓN Figura 37: Árbol de búsqueda para una triada de tipo OldChord en do mayor ubicada en la octava 0 Figura 38: Nodos solución del árbol de búsqueda de la restricción Triad para un acorde de tipo OldChord 68 MODELO E IMPLEMENTACIÓN 8 PRUEBAS Y RESULTADOS OBTENIDOS 8.1 Pruebas Internas Las pruebas hechas a los procedimientos definidos se hicieron en función de los parámetros de entrada que pueden recibir. Estas pruebas son: 1) Muza.note.tone: a) El procedimiento verifica que el literal que se pasa como parámetro para definir la relación de tonos hace parte del conjunto {' =:' , ' <:' , ' =<:' , ' >:' , ' >=:' , '\\ =:' , '::'}, de lo contrario es lanzada una excepción indicando que el literal no hace parte del conjunto de literales permitidos. La ejecución de las siguientes líneas: Nuno={Muza.note.decl} {Muza.note.tone Nuno ':=' 'B'} Produce una falla que despliega el mensaje: “Relación incorrecta para definir el tono de una nota” b) El procedimiento verifica que la lista de tonos de notas pasada como argumento sea una lista válida tal que todo τ de la lista cumpla que: τ ∈ {' C ' , ' C # ' , ' Db' , ' D' , ' D # ' , ' Eb' , ' E ' , ' F ' , ' F # ' , ' Gb' , ' G ' , ' G # ' , ' Ab' , ' A' , ' A# ' , ' Bb' , ' B'} de lo contrario se lanza una excepción indicando que el tono no representa una nota válida. La ejecución de las siguientes líneas: Nuno={Muza.note.decl} {Muza.note.octave Nuno '=:' 'P'} Produce una falla que despliega el mensaje: “nota_No_Valida('P')” 2) Muza.note.tones a) El procedimiento verifica que el literal que se pasa como parámetro para definir la relación de tonos entre dos notas hace parte del conjunto {' =:' , ' <:' , ' =<:' , ' >:' , ' >=:' , '\\ =:'}, de lo contrario es lanzada una excepción indicando que el literal no hace parte del conjunto de literales permitidos. La ejecución de las siguientes líneas: 69 MODELO E IMPLEMENTACIÓN Nuno={Muza.note.decl} Ndos={Muza.note.decl} {Muza.note.tone Nuno Ndos':=’} Produce una falla que despliega el mensaje: “Relación incorrecta para definir el tono de dos notas” 3) Muza.note.octave a) Se verificó que el literal que se pasa como parámetro para definir la relación de octava hace parte del conjunto {' =:' , ' <:' , ' =<:' , ' >:' , ' >=:' , '\\ =:' , '::'}, de lo contrario es lanzada una excepción indicando que el literal no hace parte del conjunto de literales permitidos. 4) Muza.note.octaves a) Se verificó que el literal que se pasa como parámetro para definir la relación de octavas entre dos notas hace parte del conjunto {' =:' , ' <:' , ' =<:' , ' >:' , ' >=:' , '\\ =:'}, de lo contrario es lanzada una excepción indicando que el literal no hace parte del conjunto de literales permitidos. 5) Muza.note.distance a) Se verificó que el literal que se pasa como parámetro para definir la relación de distancia entre dos notas hace parte del conjunto {' =:' , ' <:' , ' =<:' , ' >:' , ' >=:' , '\\ =:'}, de lo contrario es lanzada una excepción indicando que los parámetros son incorrectos para definir la distancia entre dos notas. b) Se verificó que las notas pasadas como parámetro sean de tipo Note, de lo contrario se lanza una excepción indicando que los parámetros son incorrectos para definir la distancia entre dos notas. La ejecución de cualquiera de las siguientes porciones de código produce una falla con el mensaje: “Parámetros incorrectos para definir la distancia entre dos notas”. local Nuno Ndos in Nuno={Muza.note.decl} Ndos={Muza.note.decl} 70 MODELO E IMPLEMENTACIÓN {Muza.note.distance Nuno Ndos ':' 3} end local Nuno Ndos X=5 in Nuno={Muza.note.decl} Ndos={Muza.note.decl} {Muza.note.distance Nuno X '=:' 3} end 6) Muza.note.getScale a) El procedimiento verifica que el parámetro dado como octavas del dominio para la escala sea el literal ‘all’, una lista de octavas permitidas, o una octava permitida, donde una octava permitida es un número entre cero y cuatro. De lo contrario se lanza una excepción indicando que la octava no es válida. La ejecución de la siguiente línea: {Muza.note.getScale 'C' major 5} Lanza una excepción con el mensaje: “definicion_Incorrecta_Octavas(5)” b) El procedimiento verifica que el modo dado a la escala sea el átomo major o el átomo minor, de lo contrario se lanza una excepción indicando el error. La ejecución de la siguiente línea: {Muza.note.getScale 'C' mayor 0} Lanza una excepción con el mensaje: “definicion_Incorrecta_Modo(mayor)” c) El procedimiento verifica que el parámetro dado como primer grado de la escala τ cumpla: τ ∈ {' C ' , ' C # ' , ' Db' , ' D' , ' D # ' , ' Eb' , ' E ' , ' F ' , ' F # ' , ' Gb' , ' G ' , ' G # ' , ' Ab' , ' A' , ' A# ' , ' Bb' , ' B'} de lo contrario se lanza una excepción indicando que la nota dada no es válida. Esto ocurre gracias a que internamente el procedimiento GetScale hace un llamado al mismo procedimiento de verificación interno que utiliza Muza.note.tone. Entonces, la ejecución de la siguiente línea: {Muza.note.getScale 'Z' major 0} 71 MODELO E IMPLEMENTACIÓN Lanza una excepción con el mensaje: “ nota_No_Valida('Z')” 7) Muza.noteSequence.tone a) El procedimiento verifica internamente que la posición dada sea un número natural mayor que cero y menor o igual al tamaño de la secuenca, una lista de posiciones válidas, una tupla de la forma ini#fin#paso, una tupla de la forma ini#fin o el literal ‘all’. De lo contrario el procedimiento lanza una excepción indicando que el parámetro no es válido. La ejecución de la siguiente línea: {Muza.noteSequence.tone '=:' 'C' NSeq 15} Lanza una excepción con el mensaje: “posicion_Incorrecta_Para_la_Secuencia(15)” b) Las demás verificaciones las hace el procedimiento Muza.note.tone, que es invocado internamente. 8) Muza.noteSequence.tones a) El procedimiento verifica internamente que se pasen valores correctos para los atributos posición inicial, posición final y distancia. De lo contrario se lanza una excepción indicando que los parámetros no son válidos. La ejecución de la siguientes línea: NSeq ={Muza.noteSequence.decl 10} {Muza.noteSequence .tones '=:' NSeq 3 7 15} Lanza una excepción con el mensaje: “posicion_ posicion_Incorrecta_Para_la_Secuencia(7#15#3) b) Las demás verificaciones las hace el procedimiento Muza.note.tones, que es invocado internamente. 9) Muza.noteSequence.octave a) El procedimiento verifica internamente que la posición dada sea un número natural mayor que cero y menor o igual al tamaño de la secuenca, una lista de posiciones válidas, una tupla de la forma ini#fin#paso, una tupla de la 72 MODELO E IMPLEMENTACIÓN forma ini#fin o el literal ‘all’. De lo contrario el procedimiento lanza una excepción indicando que el parámetro no es válido. La ejecución de la siguiente línea: NSeq ={Muza.noteSequence.decl 10} {Muza.noteSequence.octave '=:' 3 NSeq 3#12} Lanza una excepción con el mensaje: “posicion_Incorrecta_Para_la_Secuencia(3#12)”. b) Las demás verificaciones las hace el procedimiento Muza.note.octave, que es invocado internamente. 10) Muza.noteSequence.octaves a) El procedimiento verifica internamente que se pasen valores correctos para los atributos posición inicial, posición final y distancia. De lo contrario se lanza una excepción indicando que los parámetros no son válidos. La ejecución de la siguientes línea: NSeq ={Muza.noteSequence.decl 10} Muza.noteSequence.octaves '=:' NSeq 8 3 12} Lanza una excepción con el mensaje: “posicion_ posicion_Incorrecta_Para_la_Secuencia(3#12#8) b) Las demás verificaciones las hace el procedimiento Muza.note.octaves, que es invocado internamente. 11) Muza.noteSequence.distance a) El procedimiento verifica internamente que se pasen valores correctos para los atributos posición inicial, posición final y numPasos. De lo contrario se lanza una excepción indicando que los parámetros no son válidos. La ejecución de la siguientes líneas: NSeq ={Muza.noteSequence.decl 10} {Muza.noteSequence.distance '=:' 4 NSeq 2 1 17} 73 MODELO E IMPLEMENTACIÓN Lanza una excepción con el mensaje: “posicion_ posicion_Incorrecta_Para_la_Secuencia(1#17#2) b) Las demás verificaciones las hace el procedimiento Muza.note.distance que es llamado internamente. 12) Muza.chord.size y Muza.Oldchord.size a) Se verifica que el tamaño del acorde sea un número entre cero y treinta, de lo contrario se lanza una excepción indicando el motivo del error. b) Se valida que el literal que indica la relación del tamaño pertenezca al conjunto {' =:' , ' <:' , ' =<:' , ' >:' , ' >=:' , '\\ =:'}, de lo contrario el procedimiento no efectúa ninguna función sobre el acorde. 13) Muza.chord.notesIn y Muza.Oldchord.notesIn a) Se verifica que el parámetro pasado para identificar las notas que se incluirán en el acorde es una nota, o una lista de notas, de lo contrario se lanza una excepción indicando el error. 14) Muza.chord.include y Muza.Oldchord.include a) Se verifica que el parámetro pasado para identificar las notas que se incluirán en el acorde es una nota, o una lista de notas, de lo contrario se lanza una excepción indicando el error. 15) Muza.chord.notesOut y Muza.Oldchord.notesOut a) Se verifica que el parámetro pasado para identificar las notas que se excluirán del acorde es una nota, o una lista de notas, de lo contrario se lanza una excepción indicando el error. 16) Muza.chord.setDomain y Muza.Oldchord.setDomain a) Se verifica que el parámetro pasado para identificar las notas que determinarán el dominio del acorde es de tipo nota, o lista de notas, de lo contrario se lanza una excepción indicando el error. 74 MODELO E IMPLEMENTACIÓN 17) Muza.chord.notesDistance y Muza.Oldchord.notesDistance a) Se verificó que funcionan correctamente cuando el literal que indica la relación de la distancia entre cada par de notas pertenece al conjunto {' =:' , ' <:' , ' =<:' , ' >:' , ' >=:' , '\\ =:'} 18) Muza.chord.triad y Muza.Oldchord.triad a) Se verificó que funcionan correctamente cuando los atributos del primer grado de la escala, el modo y el rango de octavas son coherentes; estas verificaciones se hacen por medio del procedimiento Muza.note.getScale que es invocado internamente. 19) Muza.muzaPrint.print a) Se verificó que retorna la representación a modo de String del atributo muzaTerm que recibe sí este es de tipo Note, NoteSequence, Chord u OldChord, ya sea que esté determinado o restringido a alguno de los tipos mencionados. De lo contrario no retorna representación alguna. 8.2 EJEMPLOS Los ejemplos realizados sobre cada una de las restricciones definidas para todos los módulos de muza han sido incluidos a lo largo del capítulo 7, MUZA: DEFINICIÓN DEL SISTEMA DE RESTRICCIONES, como parte de la explicación de cada procedimiento, y los resultados arrojados por el mismo. A continuación se enuncian dos ejemplos sobre el uso de varias restricciones en conjunto. 8.2.1 Ejemplo 1 El siguiente ejemplo hace uso de la restricción triad para acordes en conjunto con las restricción include y con el procedimiento Muza.note.const que retorna una nota con sus atributos determinados por el literal de la forma tono:octava dado. 75 MODELO E IMPLEMENTACIÓN {Explorer.all proc{$Triada} MiNota10 MiNota14 in Triada={Muza.chord.decl} {Muza.chord.triad 'C' major 0 Triada} MiNota14 = {Muza.note.const 'C:0'} % MiNota10 = {Muza.note.const 'G:0'} {Muza.chord.include [ MiNota14] Triada} {FS.distribute naive [Triada]} end} El árbol de búsqueda correspondiente es el de la Figura 39, y las soluciones señaladas en el mismo se ilustran en la Figura 40. Figura 39: Árbol de búsqueda ejemplo 1 Figura 40: Nodos solución del árbol de búsqueda ejemplo 1 76 MODELO E IMPLEMENTACIÓN 8.2.2 Ejemplo 2 El siguiente ejemplo crea una secuencia de acordes a manera de lista, haciendo uso de la restricción triad para acordes en conjunto con las restricciónes include, notesOut y con el procedimiento Muza.note.const que retorna una nota con sus atributos determinados por el literal de la forma tono:octava dado. La secuencia de acordes del ejemplo se manipula gracias a los procedimientos de Oz para listas. {Explorer.all proc{$ChordSequence} {List.make 5 ChordSequence} {ForAll ChordSequence proc{$ El} {Muza.chord.decl El} {Muza.chord.triad 'C' major 0 El} end} {For 1 5 2 proc{$ I} {Muza.chord.include {Muza.note.const 'C:0'} {List.nth ChordSequence I}} {Muza.chord.notesOut {Muza.note.const 'G:0'} {List.nth ChordSequence I}} end} {For 2 5 2 proc{$ I} {Muza.chord.notesOut {Muza.note.const 'E:0'} {List.nth ChordSequence I}} end} end} {FS.distribute naive ChordSequence} El árbol de busqueda correspondiente a la ejecución de este ejemplo se ilustra en la Figura 41, y los nodos solución del árbol se muestran en la Figura 42. 77 MODELO E IMPLEMENTACIÓN Figura 41: Árbol de búsqueda para el ejemplo 2 Figura 42: Soluciones para el ejemplo 2 78 MODELO E IMPLEMENTACIÓN CONCLUSIONES 9 CONCLUSIONES Se cumplieron los objetivos planteados para el proyecto, demostrando así que es posible realizar un sistema de estructuras musicales y restricciones para armonía en Mozart que permitan manipular los dominios de dichas estructuras de modo coherente con la teoría musical, (MuZa es el resultado). Además, también es posible fortalecer y expandir el modelo presentado adicionando características además de las armónicas y mejorando las propuestas, esto gracias a las reglas que la teoría musical expone sobre las cualidades propias de la música que la hacen manejable a través de modelos de variables, dominios y restricciones. Oz es un lenguaje de programación muy robusto, y ofrece las características ideales que la programación concurrente por restricciones necesita para trabajar de forma eficiente. Las facilidades dadas por las librerías del módulo de programación por restricciones de Mozart hacen muy cómoda la labor de modelar distintas estructuras a partir de las que ya están soportadas dada la forma como están implementados los distintos propagadores, que hace más fácil abstraer los conceptos básicos, y la documentación que gira alrededor de las funcionalidades y librerías de Mozart. El paradigma de programación por restricciones es ideal para modelar estructuras musicales y las relaciones que existen entre dichas estructuras gracias a las numerosas reglas que definen la teoría musical. La abstracción de la teoría musical y su “traducción” o interpretación a modelos de programación por restricciones resulta casi natural y de fácil entendimiento a lo largo de la implementación de los modelos. Las características del paradigma de programación por restricciones unidas con la riqueza en expresividad de Oz y los módulos de Mozart que soportan dicho paradigma, hacen que MuZa, el sistema de restricciones y estructuras musicales propuesto, resulte fácilmente extensible para futuros aportes, ya que su implementación es rica en expresividad, no sólo para quien desee utilizar los procedimientos definidos, sino para quienes deseen extender y mejorar los módulos de MuZa; esto es gracias a que el modelo seleccionado 79 MODELO E IMPLEMENTACIÓN obedece definiciones comunes, y muy sencillas, sobre las estructuras musicales que se trabajaron. La teoría musical sobre armonía es demasiado amplia, y las restricciones que se pueden implementar sobre un conjunto de estructuras musicales son muchas; aunque uno de los objetivos de la composición musical es dar rienda suelta a la creatividad de un compositor, este se rige por ciertas reglas invariantes que pueden modelarse como restricciones. Hay otras reglas que rigen estilos de composición característicos a una época, zona geográfica o compositor en particular, estas reglas también pueden ser modeladas, pero no hay una garantía de que sean igual de valiosas para todos los compositores, ya que habrán algunos que deseen innovar e ir más allá de los estilos tradicionales proponiendo sus propias reglas. La documentación que gira alrededor de Mozart es muy completa, por ejemplo [15], [19], [26] y [27], resulta adecuada cuando se desea implementar un sistema de restricciones en Oz a partir de las estructuras existentes y las restricciones definidas en Mozart para las mismas. Para implementar un sistema de restricciones para Mozart es de gran importancia estudiar muy bien los modelos tentativos, ya que gracias al análisis de dichos modelos se puede determinar si es necesario construir un sistema de restricciones desde la nada, (Mozart ofrece una interfase con C++ y toda la documentación necesaria para suplir este propósito), o si es posible modelar las estructuras y el sistema de restricciones alrededor de ellas a partir del módulo de programación por restricciones que tiene Mozart y las librerías contenidas en él. La diferencia entre ambos métodos es grande, y debe estudiarse con cuidado. El modelo de definición de un acorde implementado en el módulo Muza.chord es mucho más eficiente y fácil de manejar que el modelo implementado en el módulo Muza.oldChord. Además, gracias a la implementación del modelo de Muza.chord, resultará mucho más fácil la implementación de secuencias de acordes y las restricciones sobre ellas como futuros aportes a MuZa. 80 MODELO E IMPLEMENTACIÓN 10 VALOR DE LA INVESTIGACIÓN Aunque MuZa es un sistema de restricciones básicas sobre estructuras musicales sencillas que no contemplan atributos de dinámica ni de temporalidad, el aporte que se hace a través de MuZa es significativo, ya que representa un primer paso para el desarrollo y fortalecimiento de nuevas características sobre estructuras musicales en MoZart a modo de procedimientos reutilizables que más adelante podrían comunicarse con interfases gráficas, multimedia y con otros lenguajes de programación como Java y C++ explotando las fortalezas del paradigma de programación por restricciones e incrementando las posibilidades de expansión de MuZa . Se espera que este trabajo sirva como puerta a más investigaciones dentro del campo de la composición musical asistida por computador, que se encarguen de añadir propagadores no sólo referentes a restricciones de armonía, sino a los demás aspectos musicales que no están dentro del alcance de este proyecto, como temporalidad concurrente, manejo de archivos de sonido, y el desarrollo de un ambiente de programación musical visual entre otros. 10.1 TRABAJO FUTURO Incrementar las características de las estructuras musicales para que puedan soportarse restricciones de otro tipo sobre ellas. Mejorar la forma como MuzaPrint despliega los resultados en pantalla, añadiéndole características gráficas más fáciles de interpretar. Escribir un artículo que exponga las características del sistema de restricciones musicales implementado en Mozart Mejorar las restricciones definidas sobre las estructuras musicales y generar la documentación técnica pertinente sobre las mismas. 81 ANEXOS IV ANEXOS 11 DETALLES SOBRE LA IMPLEMENTACIÓN 11.1 Construcción de MuZa Cada módulo de MuZa fue implementado en OZ, haciendo uso de las propiedades del lenguaje para el manejo y definición de restricciones sobre dominios y conjuntos finitos, programación concurrente por restricciones, y programación de aplicaciones modulares con Oz y Mozart [27]. Internamente, cada módulo de MuZa es la definición de un functor, (módulos en Oz), que define los procedimientos que encapsulan las restricciones correspondientes a cada módulo. 11.1.1 Compilación: Ozc Cada definición de functors está inmersa dentro de un archivo con extensión .oz, estos archivos han sido compilados invocando el compilador de Oz, ozc, así: ozc ozc ozc ozc ozc -c –c –c –c –c Note.oz –o Note.ozf NoteSequence.oz –o NoteSequence.ozf Chord.oz –o Chord.ozf OldChord.oz –o OldChord.ozf MuzaPrint.oz –o MuzaPrint.ozf 11.1.2 Creación de MuZa Para crear MuZa como la unión de los módulos compilados, es necesario crear un functor que importe cada uno de los functors compilados y los exporte para su posterior llamado desde un solo módulo raiz: MuZa. Del mismo modo debe compilarse el módulo raiz así: ozc –c Muza.oz –o MuzaRoot.ozf Para enlazar todos los módulos de MuzaRoot.ozf en uno solo que incluya todos los demás y que pueda instalarse en cualquier parte para su posterior uso se utiliza ozl, la herramienta para hacer deployment de Oz. ozl –v MuzaRoot.ozf –o Muza.ozf 82 ANEXOS De este modo, Muza.ozf contiene el sistema de restricciones en su plenitud, que podrá utilizarse con solo hacer llamado a Muza.ozf. 11.2 Utilización de MuZa Para hacer uso de los procedimientos de MuZa desde el OPI de Mozart, (Oz Programming Ingerface), y utilizar el procedimiento de MuzaPrint para la representación de resultados basta con incluir las siguientes líneas código: declare Muza P [Muza]={Module.link ['Muza.ozf']} P = proc {$ S} {Browse {Muza.muzaPrint.print S}} end {Browser.object add(P label:'MuZa Print..')} {Browser.object option(representation strings:true)} {Browser.object set(P)} La ejecución del código anterior permite que al hacer llamados al procedimiento Browser.browse sobre un término x, se pueda aplicar el procedimiento Muza.muzaPrint.print sobre lo que el Browser7 despliega, es decir: primero aparecerá en pantalla la representación que Mozart hace de x, y luego, al seleccionar la representación de x y hacer clic sobre la misma con el botón central del Mouse, o seleccionando la opción “Apply Action”, del menú “Selection”, se aplicará el la función print de muzaPrint y el resultado correspondiente aparecerá en la siguiente línea del Browser. Del mismo modo, para acceder a los nodos de un árbol de búsqueda a través de MuzaPrint se debe indicar al Explorer8 que la función de inspección de nodos será la definida por MuzaPrint.print así: {Explorer.object add(information proc{$ I X} {Inspector.configure widgetShowStrings true} {Inspector.inspect I#{Muza.muzaPrint.print X}} end label: 'InspectMuza') Browser [29] Herramienta concurrente de salida, utilizada para desplegar información posiblemente parcial sobre el estado de las variables. 8 Explorer [30]: Herramienta gráfica e interactiva para visualizar y analizar árboles de búsqueda en Mozart. 7 83 Referencias Bibliográficas V Referencias Bibliográficas [1] Douglas Hofstadter. Godel, Escher, Bach: An Eternal golden braid. Basic Books 1979. [2] M. T. Pearce, D. Meredith, and G. A. Wiggins. Motivations and methodologies for automation of the compositional process. To appear in Music Scienti, 6(2), 2002. http://citeseer.ist.psu.edu/pearce02motivations.html [3] Schoenberger, Joy Marie. Genetic Algorithms for Musical Composition with Coherency Through Genotype. Tesis de maestría en ciencias de la computación College of William and Mary, Williamsburg 2002 [4] Jacob, B. 1995. Composing with genetic algorithms. In Proceedings of the 1995 International Computer Music Conference, Banff, Alberta. http://citeseer.ist.psu.edu/jacob95composing.html [5] Niall Griffith, Peter M. Todd, Musical Networks: Parallel Distributed Perception and Performance. MIT Press 1999. [6] Sara Lewis, Chaos Music. Engineers' Forum Volume 21 Nº 3. Septiembre 2002. http://filebox.vt.edu/eng/forum/ [7] C. Schulte. Finite Domain Constraint Programming in Oz: A Tutorial. German Research Centre for Artifical Intelligence (DFKI), Feb 1998. http://www.ps.unisb.de/oz/documentation. [8] François Pachet, Olivier Delerue, Peter Hanappe. Dynamic audio mixing (2000). http://citeseer.ist.psu.edu/pachet00dynamic.html 84 Referencias Bibliográficas [9] Mogens Nielsen, Catuscia Palamidessi and Frank D. Valencia. Temporal Concurrent Constraint Programming: Denotation, Logic and Applications. In Special Issue of Selected Papers from EXPRESS'01, © Nordic Journal of Computing. 2002 [10] Martin Henz, Stefan Lauer, and Detlev Zimmermann. COMPOzE--Intentionbased Music Composition through Constraint Programming. In Proc. IEEE Int. Conf. on Tools with Artificial Intelligence, Nov. 1996, Toulouse, France. [11] Carlos Agon, Gérard Assayag, Olivier Delerue, Camilo Rueda. Objects, time and constraints in openMusic. In: ICMC´98, 1998, Ann Arbor, Michigan. proceedings ICMC 98. San Francisco: international computer music association ICMA, 1998. [12] Carlos Agon, Gérard Assayag, Mikael Laurson, Camilo Rueda. Computer Assisted Composition at Ircam : PatchWork & OpenMusic. Computer Music Journal 23:3, otoño 1999. [13] Camilo Rueda, Gloria Alvarez, Luis O. Quesada, Gabriel Tamura, Frank D. Valencia, Juan Francisco Díaz, Gerard Assayag, Integrating Constraints and Concurrent Objects in Musical Applications: A Calculus and its Visual Language. Constraints Journal. Amsterdam: , v.6, n.1, p.21 - 52, 2001 [14] Charlotte Truchet. Constraintes, Recherche locale et composition asisteé par ordinateur Tesis doctoral, Universidad de Paris 2004 [15] Tobias Müller, The Mozart Constraint Extensions Tutorial. In: Mozart Documentation 2004. http://www.mozart-oz.org/documentation/cpitut/index.html 85 Referencias Bibliográficas [16] J.Raso del Molino, La Armonía. En : Revista en internet de música culta, Filomúsica. Nº 1 febrero 2000. http://www.filomusica.com/filo1/jr.html [17] Rueda Camilo, Bonnet Antoine. OpenMusic Situation versión 3.0. IRCAM 1999 [18] Gérard Assayag (Ircam) , Shlomo Dubnov (Ben Gurion Univ.), Olivier Delerue (Ircam), Guessing the Composer's Mind: Applying Universal Prediction to Musical Style. Proceedings of the International Computer Music Conference. International Computer Music Association, pp. 496-499. [19] Seif Haridi, Nils Franzén. Tutorial of Oz. In: Mozart Documentation 2004. http://www.mozart-oz.org/documentation/tutorial/index.html [20] The Mozart Programming System www.mozart-oz.org [21] Quesada, L., C. Rueda, and G. Tamura: 1997, `The visual model of Cordial'. In: Proceedings of the CLEI97. Valparaiso, Chile. [22] Piston, Walter. Armonía. Editorial IDEA BOOKS 2001 [23] Randel Don. Diccionario Harvard de Música. Editorial Alianza 1999. [24] Ibaibarriaga, Iñigo. KURAIA, Grupo de Música contemporánea de Bilbao. Música y Matemáticas. De Schoenberg a Xenakis. Centro virtual de divulgación de las matemáticas. http://www.divulgamat.net/weborriak/TestuakOnLine/03-04/PG03-04ibaibarriaga.pdf 86 Referencias Bibliográficas [25] Anders, Torsten. Strasheela: Desing and Usage of a Music Composition Environment Base don the Oz Programming Model. In: Second International Mozart/Oz Conference MOZ 2004. Octubre 2004. [26] Müller Tobias. Constraint Propagation in Mozart. Doctoral dissertation, Universität des Saarlandes, Naturwissenschaftlich-Technische Fakultät I, Fachrichtung Informatik, Saarbrücken, Germany, 2001. [27] Duchier Denys, Kornstaedt Leif and Schulte Christian. Application Programming, introduction to application programming with Oz and Mozart. Version 1.3.2, 2006. http://www.mozart-oz.org/documentation/apptut/index.html [28] La Motte, Diether de. Armonía. Editorial IDEA BOOKS 1998 [29] Popov, Konstantine. The Oz Browser. In: Mozart Documentation. Versión 1.3.1 1 2004-06-17. [30] Schulte, Christian. Oz Explorer - Visual Constraint Programming Support. In Mozart Documentation. Versión 1.3.1 1 2004-06-17. 87