Arquivo da categoria ‘Programação’

Atualmente, no campos das aplicações te técnicas de inteligência artificial, principalmente se tratando de algoritmos bio-inspirados, os algoritmos genéticos tem um grande destaque.

É muito comum vermos aplicações de otimização combinatória que utilizam esse tipo de técnicas, no entando, ela pode ser muito mais do que simples buscas aleatórias e pode ter aplicações nos mais variados campos do conhecimento.

O  principal objetivo desse post é mostrar como essa técnica pode ser aplicada no ensino do dedilhado pianístico. Primeiramente vou abordar sobre os aspectos musicais  e em seguida , a aplicação da técnica.

A música e as dificuldades de aprendizado

Durante a fase de aprendizagem de uma obra musical, por exemplo o piano, o aluno  iniciante, algumas vezes se sente desmotivado pelo não conhecimento da seqüência dos dedos a serem aplicados nas diferentes teclas do instrumento seguindo a linha melódica indicada por uma partitura musical.

“Por isso é fundamental a presença constante do professor junto ao aluno”

A partir de exemplos corretos do dedilhado pianístico, o aluno tem um melhor aprendizado. Além disso, é importante que o aluno não crie vícios mecânicos no dedilhado.

Os vícios mecânicos prejudicam o andamento do dedilhado e o aprendizado da peça musical. Assim, é necessário que o aluno conheça a priori a seqüência do dedilhado a ser usado nos trechos da peça para que sua interpretação seja a melhor possível.

A música é construída por sucessões de sons por grau conjunto (esquema de caráter escalístico) ou graus disjuntos (tipo arpejos ou acordes), ou por uma mistura de ambos. Portanto, o número de combinações possíveis é enorme. Os dedilhados, isto é, as diversas associações de dedos necessárias para executá-los são também muito grandes.

Uma seqüência de apenas quatro notas , dependendo do contexto onde está inserida, pode ser digitada, pelo menos de 17 maneiras diferentes :

Sequência Melódica de quatro notas

Dedilhado pianístico ótimo: Aquele que o aluno consiga executar o trecho musical da forma mais cômoda possível (sem tensões musculares) e , quando o trecho exigir velocidade de execução, o  pianista tem de fazê-lo da melhor maneira possível.

Dependendo das características físicas da mão de um aluno, um dedilhado pode ser melhor do que outro.

Atualmente, com o avanço e o baixo custo dos computadores, é possível o desenvolvimento de Sistemas Inteligentes para auxiliar o ensino do dedilhado pianístico.

Nesse contexto é que inserimos o uso de algumas técnicas de IA, no caso, os algortimos genéticos.

Acima foi falado sobre as várias combinações para uma sequ6encia simples de 4 notas musicais. Qual a melhor? Qual a de menos custo para o músico? Perguntas como essas são respondidas ao utilizar essa técnica fantástica e de fácil compreensão.

Relembrando…

Algoritmo Genético (AG) é um procedimento iterativo, que mantém umapopulação de estruturas (chamadas indivíduos, espécies ou cromossomos) que representam possíveis soluções de um determinado problema.
Os AG são sistemas que se baseiam nos mecanismos da evolução dos seres vivos. Possíveis soluções de um problema são combinadas através dos operadores genéticos específicos inspirados na Seleção Natural de Charles DARWIN (1809- 1882), no Cruzamento e na Mutação.

O AG tem como principal característica a geração de um conjunto de soluções ao invés de uma única solução.

Basicamente, esses operadores modificam as estruturas (ou cromossomos) do problema, e sobrevivem para a próxima geração, os mais aptos dentre essa população de indivíduos.

Há uma troca aleatória, porém estruturada, de informações entre esses cromossomos (cruzamento), de modo que, a cada geração, um novo conjunto de cromossomos é criado baseado nos mais aptos da geração anterior.

As mutações nos genes dos cromossomos são usualmente geradas de forma aleatória, mas os métodos são determinísticos e em geral podem ser considerados como sendo do tipo genético com regras de mutações determinísticas.

Aplicação…

O Algoritmo Genético caracteriza-se por um processo de seleção baseado no desempenho e na população de cromossomos. A cada seqüência do dedilhado pianístico é atribuído um cromossomo. Os elementos da população são listas fixas de parâmetros a serem otimizadas baseadas numa determinada medida de desempenho (“fitness”).

O AG possui 5 componentes básicos:

  1. Um método para codificação dos cromossomos (por exemplo, o conjunto representando a seqüência de dedilhado da mão direita {1;2;3;4;5}, onde os numerais representam genes);
  2. Uma função objetivo “fitness” (menor distância e posicionamento);
  3. Uma população inicial (50 cromossomos);
  4. Um conjunto de operadores para formarem a evolução entre dois cromossomos de populações consecutivas (mutação e cruzamento), que são usados entre as posições dasespécies, por exemplo, ({1;2;3;4;5} -> {2;1;3;4;5});
  5. Parâmetros de trabalho (por exemplo, 2% de probabilidade de mudança no cromossomo)
Como funciona…

Abaixo, segue o esquema padrão do teclado de piano que possui 52 teclas brancas e 36 teclas pretas. A cada tecla branca é atribuído um número que corresponde à nota e posição no teclado, recebendo valores compreendidos entre –23 a +28 com o dó central sendo igual a zero:

O cálculo do comprimento do dedilhado pianístico baseia-se na proximidade física dos dedos.

Por exemplo, assumindo-se que o intervalo de segundas recebe valor igual a um, e se o polegar estiver sobre a primeira nota e a próxima nota for vizinha ascendente, então o comprimento será igual a um. O deslocamento do polegar assume valor menor ou igual a quatro, que é um intervalo de quinta justa ascendente para a mão direita ou descendente para a mão esquerda. Entre os dedos indicador, médio e anular, a distância máxima é de apenas duas teclas dependendo de certos critérios.

No exemplo a seguir ,os melhores dedos seriam 2 1 2 3 5, pois o intervalo do contexto da frase musical é de uma oitava.

Começando com dedo 2 no dó e fazendo a passagem do polegar sob dedo 2 para alcançar o ré com o polegar, ficamos com um intervalo de 3a para ser executado com o primeiro e segundo dedos. Um intervalo de 2a para tocar com os dedos 2 e 3 e finalmente um intervalo de 5a para ser executado com os dedos 3 e 4.

A numeração dos dedos são armazenados no vetor dedos[5] e as notas no vetor teclas[5]. Para notas apenas ascendentes ou descendentes, o comprimento total das notas inseridas no teclado recebe valor igual a soma dos módulos das diferenças entre as notas consecutivas.

Por exemplo, o conjunto do dedilhado {n1; n2; n3; n4; n5} resulta em:

D = |n2-n1| + |n3-n2| + |n4-n3| + |n5-n4|

Abaixo segue um exemplo de como é calculado o comprimento de uma frase musical ascendente. Neste caso o comprimento é igual a cinco, pois: D = |2-0| + |4-3|+ |5-4| + |6-5| = 5.

Se uma nota é ascendente ou descendente em relação a sua antecessora, o comprimento da frase musical é definido como: D12 = |notas[2] – notas[1]| + |d2-d1-1|.

Se as notas forem ascendentes e a seqüência dos dedos decrescentes ou então, se as notas forem descendentes e a seqüência dos dedos crescentes então: D12 = 2 * ( |notas[2] – notas[1]|) + |d2-d1-1|

Usando o AG, pode-se inserir a seqüência de notas e também definir, se quiser, a seqüência dos dedos que melhor se adapte, ou então ele poderá solicitar que encontre as dez melhores opções de seqüência de dedilhado. A escolha é feita de acordo com o menor comprimento da seqüência do dedilhado calculado pelo AG.

Esse post é uma adaptação de um artigo que li recentemente e gostei muito. Ele pode ser encontrado aqui.

 

Dicas, sugestões, críticas e sugestões para os próximos posts, deixem nos comentários. Se preferirem, podem mandar email para gabriel@ecomp.eng.br

 

Anúncios

Olá amigos,

Esse post é a apresentação feita para a SITEC 2010 – Semana do Instituto Tecnológico da Universidade Federal do Pará.

Consiste em uma compilação de várias referências encontradas em livos e na internet.

Espero que gostem!
Dúvidas, críticas e sugestões, usem os comentários ou mandem email para jgabriel.ufpa@gmail.com , ficarei feliz em ajudar.

Então amigos, agradeço todos os comentários e conforme foi combinado, estou postando a segunda parte do post sobre desenvolvimento bluetooth utilizando JAVA.

No primeiro post, tratei da base da tecnologia bluetooth, além de algumas informações obre a plataforma Java SE e ME.

Hoje venho apresentá-los o Marge Framework. Essa sequência terá um TERCEIRO post, que será composta pelos códigos comentados por mim, para que possa facilitar a compreensão e aprendizagem de vocês. Lembrando que, qualquer dúvida, podem deixar nos comentários, ou mandar email, eu terei grande satisfação em ajudá-los.

O conteúdo desse post é uma adaptação/compactação dos trabalhos apresentado pelos seus próprios criadores. Esses documentos podem ser encontrados aqui.

O projeto Marge é um framework desenvolvido em Java – que utiliza a biblioteca JSR 82 – com intuito de ajudar a criação de aplicações Bluetooth que fazem parte de um contexto comum.

A idéia principal do projeto é reduzir a curva de aprendizado para desenvolvedores que pretendem criar aplicações com Bluetooth com objetivo de torná-los mais produtivos, fazendo-os concentrar o foco do desenvolvimento apenas na parte lógica do software.

O framework se responsabilizará por abstrair as outras partes relacionadas à comunicação Bluetooth – como as conexões, protocolos, trocas de mensagens, pesquisa por dispositivos e serviços – de uma maneira fácil e suportando diferentes configurações.

O projeto Marge não propõe apenas uma biblioteca para simplificar o uso de Blueooth em Java, mas sim toda uma arquitetura definida pelo framework.

Abaixo temos  a imagem detalhada de onde se dá o uso do Marge na arquitetura para desenvolvimento Bluetooth.

Na primeira camada temos o sistema operacional, seguido de uma pilha de protocolos Bluetooth, e de uma camada de integração entre a máquina virtual Java e a chamada para a pilha. Acima da máquina virtual Java está a JSR 82, a API que especifica o Bluetooth sobre a qual o Marge foi desenvolvido. Acima do Marge, encontram-se as aplicações.

Arquitetura do Marge Framework

O projeto Marge é livre e possui o código aberto registrado sobre a licensa LGPL (GNU Lesser General Public License) e hospedado pelo portal java.net no endereço http://marge.dev.java.net.

O projeto faz parte da comunidade Mobile and Embedded do portal java.net, que é responsável pelo projetos de código aberto em Java ME.

Pacotes e classes

O framework Marge contém 24 classes divididas em 7 pacotes. Cada pacote irá ser detalhado abaixo.

O pacote net.java.dev.marge.communication contém a estrutura básica para comunicação. Este pacote contém as seguintes classes:

  • ClientCommunication: Interface que define métodos para um cliente Bluetooth poder se conectar.
  • Communicable: Classe abstrata que define um esqueleto de como funciona a conexão e as trocas de mensagens entre o cliente e servidor.
  • CommunicationListener: Interface que define métodos relativos ao fechamento da conexão, recebimento de mensagens, erros durante o recebimento e troca de mensagens.
  • ServerCommunication: Interface que define métodos para um servidor Bluetooth poder conectar.

O pacote net.java.dev.marge.communication.l2cap contém as classes especializadas para a comunicação utilizando o protocolo L2CAP.

  • ClientL2CAPCommunication: Classe que implementa a conexão em L2CAP por parte do cliente.
  • L2CAPCommunication: Classe abstrata que define um esqueleto de como funciona a conexão e as trocas de mensagens entre o cliente e servidor L2CAP.
  • ServerL2CAPCommunication: Classe que implementa a conexão em L2CAP por parte do servidor.

O pacote net.java.dev.marge.communication.rfcomm, contém as classes especializadas para a comunicação utilizando o protocolo RFCOMM.

  • ClientRFCOMMCommunication: Classe que implementa a conexão em RFCOMM por parte do cliente.
  • RFCOMMCommunication: Classe abstrata que define um esqueleto de como funciona a conexão e as trocas de mensagens entre o cliente e servidor RFCOMM.
  • ServerRFCOMMCommunication: Classe que implementa a conexão em RFCOMM por parte do servidor.

O pacote net.java.dev.marge.entity contém as entidades básicas do framework.

  • Client: Interface que define métodos de um cliente genérico.
  • ClientDevice: Classe que define a estrutura de um dispositivo cliente.
  • Device: Classe abstrata que define a estrutura de um dispositivo genérico.
  • Server: Interface que define métodos de um servidor genérico.
  • ServerDevice: Classe que define a estrutura de um dispositivo servidor.

O pacote net.java.dev.marge.entity.config contém as configurações necessárias para que o framework instancie um cliente ou servidor.

  • ClientConfiguration: Classe abstrata de configuração de um cliente.
  • Configuration: Classe abstrata de configuração genérica.
  • ServerConfiguration: Classe abstrata de configuração de um servidor

O pacote net.java.dev.marge.factory contém as fábricas, responsáveis pela instanciação de clientes e servidores para cada protocolo.

  • AbstractCommunicationFactory: Interface que define métodos para criação de dispositivos clientes e servidores.
  • L2CAPFactory: Classe que define métodos para criação de dispositivos clientes e servidores que usam o protocolo L2CAP para comunicação.
  • RFCOMMCommunicationFactory: Classe que define métodos para criação de dispositivos clientes e servidores que usam o protocolo RFCOMM para comunicação.

O pacote net.java.dev.marge.inquiry contém as classes especializadas pelas buscas de dispositivos e serviços que envolvem o protocolo SDP, utilizado para descoberta de serviços.

  • DevicesFoundListener: Interface que contém métodos relativos a busca de dispositivos.
  • Discoverer: Classe que realiza a busca de dispositivos e serviços.
  • ServicesFoundListener: Interface que contém métodos relativos a busca de serviços.
Como começar?

Para criar uma instância de um servidor – representado pela classe ServerDevice do pacote net.java.dev.marge.entity – ou cliente – representado pela classe ClientDevice desse mesmo pacote – primeiramente é necessário definir o protocolo de comunicação a ser adotado.

  • Caso se decida pelo RFCOMM, todas as instâncias criadas, do tipo cliente ou servidor, serão instanciadas através da fábrica RFCOMMComunicationFactory;
  • Caso seja a L2CAP, será usada a fábrica L2CAPComunicationFactory.

As fábricas pertencem ao pacote net.java.dev.marge.factory e possuem os métodos createClient e createServer, que retornam o tipo específico de Device que contém os métodos que podem ser invocados.

Cada um desses métodos recebe como parâmetro uma instância concreta da classe Configuration do pacote net.java.dev.marge.entity.config, podendo ser uma ServerConfiguration ou ClientConfiguration.

Inicialmente, essas configurações já possuem alguns valores padrão para funcionar, porém eles podem ser alterados manualmente caso necessário.

Um ServerConfiguration deve obrigatoriamente receber, no construtor, um CommunicationListener, que é uma interface pertencente ao pacote net.java.dev.marge.communication que define métodos para tratamento das seguintes situações: quando uma mensagem é recebida; quando ocorre um erro na recepção de uma mensagem; quando ocorre um erro no envio de uma mensagem; e quando uma conexão é estabelecida.

Um ClientConfiguration deve também obrigatoriamente receber um CommunicationListener no construtor, porém também deve receber um objeto que implemente a interface DevicesFoundListener, do pacote net.java.dev.marge.inquiry, que contém métodos associados à busca por dispositivos e a possíveis erros encontrados nessa busca; e um objeto que implemente a interface ServicesFoundListener, deste mesmo pacote, que contém métodos associados à busca por serviços e a possíveis erros encontrados.

  1. Um servidor RFCOMM é criado através da configuração mandada por parâmetro para a fábrica.
  2. Após isso, a sua escuta é iniciada.
  3. Quando alguém se conectar a ele, o listener2, definido pela interface net.java.dev.marge.communication.ConnectionListener, irá avisá-lo.
  4. Após a conexão, o servidor pode enviar normalmente mensagens para o cliente conectado e ele será também notificado, pelo mesmo listener, das mensagens que forem recebidas.
  5. Em seguida são mostrados alguns trechos de código que demonstram como o framework é utilizado pelo servidor.

Instanciando um servidor com a comunicação RFCOMM e iniciando sua escuta:

AbstractCommunicationFactory factory = new RFCOMMCommunicationFactory();
ServerConfiguration sconf = new ServerConfiguration(new CommunicationListenerImpl());
ServerDevice server = (ServerDevice) factory.createServer(sconf);
server.start();

Servidor enviando uma mensagem:

server.send("Test message");
  1. Um cliente RFCOMM é criado através da configuração mandada por parâmetro para a fábrica.
  2. Após isso, ele faz uma busca por dispositivos com Bluetooth ligado. O listener, definido pela interface net.java.dev.marge.inquiry.DevicesFoundListener,  retorna os dispositivos encontrados.
  3. Depois faz-se uma busca pelos serviços desejados no dispositivo encontrado escolhido. O listener, definido pela interface net.java.dev.marge.inquiry.ServicesFoundListener, retorna o serviço, caso ele seja encontrado.
  4. Com esse serviço, o dispositivo cliente se conecta ao servidor e é notificado pelo listener, definido pela interface net.java.dev.marge.communication.ConnectionListener, que houve a conexão.
  5. Após a conexão, o cliente pode enviar  normalmente mensagens para o servidor e ele será também notificado, pelo mesmo listener, das mensagens que forem recebidas.

A seguir são apresentados alguns trechos de código relacionados ao uso do framework no cliente:

Instanciando um cliente com comunicação RFCOMM e iniciando um busca por dispositivos:

AbstractCommunicationFactory factory = new RFCOMMCommunicationFactory();
ClientConfiguration cconf = new ClientConfiguration(new ServiceListenerImpl(), new
DevicesListenerImpl(), new CommunicationListenerImpl()));
ClientDevice client = (ClientDevice) factory.createClient(cconf);
client.startInquiry(DiscoveryAgent.GIAC);

Cliente iniciando uma busca por serviços em um determinado dispositivo encontrado:


client.searchServices(client.getUuidset(), remoteDeviceFound);

Cliente conectando-se a um serviço encontrado previamente:

client.connect(serviceRecordFound);

Cliente enviando uma mensagem:

client.send("Test message");

Dúvidas, críticas e sugestões. Usem os comentários, ou mandem email para gabriel@ecomp.eng.br

 

Terei grande satisfação em ajudar!

Até o próximo post!

Bluetooth é uma tecnologia sem fio muito usada para conectar dispositivos a curta distância, que ganhou bastante espaço nos últimos anos por estar disponível na maioria dos celulares e notebooks mais recentes.

A linguagem de programação Java, atualmente, também aparece como uma das principais plataformas para o desenvolvimento de aplicações em vários dispositivos, devido as diversas vantagens que a mesma possui.

Java possui uma especificação para uso de Bluetooth, definida pela JSR 82, criada – e finalizada sua segunda versão em 2006, mas esta, por conseguinte, possui um difícil aprendizado. Sendo assim, esta sequencia de posts apresentam  apresentam a estrutura conceitual da tecnologia bluetooth e sua implementação em  java utilizando o Marge Framework com o intuito de facilitar o desenvolvimento de aplicações.

Para permitir a integração entre as tecnologias Bluetooth e Java foi criada – e finalizada sua segunda versão em 2006 – a Java APIs for Bluetooth, conhecida por JSR 82. A JSR 82 atualmente está disponível em diversos dispositivos e define a especificação para comunicação Bluetooth em diversos níveis. Com toda essa facilidade de suporte por parte da linguagem, e com a grande adoção do Bluetooth pelos fabricantes, se faz possível, assim, a criação de diversas aplicações interessantes e/ou de dispositivos que utilizam essa tecnologia para cenários distintos, tais como em casa, no trabalho, no lazer ou qualquer outro ambiente que requeira mobilidade.

Diferentes dispositivos Bluetooth podem oferecer diferentes serviços. Um dispositivo Bluetooth, após ter encontrado um outro dispositivo remoto, poderá fazer uma pesquisa pelo serviços disponíveis nesse dispositivo remoto ou apenas por algum serviço específico. O serviço de pesquisa de dispositivos utiliza o protocolo SDP (Service Discovery Protocol).

Em um contexto SDP, um cliente envia requisições a um servidor que, por sua vez, envia as informações de serviços disponíveis nele. Dispositivos Bluetooth mantém informações sobre seus serviços em um Service Discovery DataBase (SDDB). Um SDDB contém entradas de registros de serviços onde cada um desses registros contém atributos que o descrevem.

Em nossos artigos apresentaremos as implementações de conexão via bluetooth entre um celular e o pc, para isso faremos uma breve introdução das tecnologias Java SE e Java ME.

O Java SE está dividido em três partes:
• Componentes do núcleo ou core: Provê funcionalidades essenciais para escrita de programas, para acesso a banco de dados, segurança, invocações de procedimentos remotos e comunicação.
• Componentes do cliente ou desktop: Provê facilidades para ajudar na construção de aplicações para os usuários. Isso inclui componentes de desenvolvimento como os Java Plug-in, APIs de modelos de componentes como os JavaBeans, interfaces gráficas para os usuários, etc.

Java ME é destinado aos dispositivos com recursos limitados. Esse dispositivos englobam os celulares, PDAs, set-top boxes – conversores usados em televisão digital – e outros aparelhos com essas características. Antes da introdução do Java ME, a maioria destes dipositivos eletrônicos possuía uma natureza estática, por não permitir a instalação de novos softwares, além daqueles que foram inseridos no processo de fabricação. Porém, atualmente, é possível torná-los muito mais dinâmicos.

Apesar dessas grandes vantagens, a tecnologia Java ME ainda possui certas restrições que estão aos poucos sendo sanadas, pois embora fosse desejável ter toda a API Java SE nos dispositivos micro, isso não é nada realístico hoje.

Por exemplo, um celular, com sua tela limitada, não poderia usar todas as APIs de interface gráfica disponíveis na versão do Java para desktop, tão quanto suportar as APIs relativas ao desenvolvimento em Java para servidores, que também envolvem questões muito mais complexas.

Para resolver esse problema e dar uma maior flexibilidade ao Java ME, foram criados os conceitos de configurações, perfis e pacotes adicionais, conforme ilustrado na figura:

Atualmente, o Java ME divide as configurações em dois tipos, ilustrados abaixo configurações mais limitadas, chamadas de CLDC (Connected Limited Device
Configuration), e configurações com mais recursos, a CDC (Connected Device Configuration). A CLDC é um subconjunto da CDC, como mostra a figura:

No próximo post mostrarei a implementação de um programa de comunicação via Bluetooth entre 2 celulares e entre pc e celular.

Dúvidas, críticas e opiniões, deixem nos comentários.

Obrigado!