sexta-feira, agosto 26, 2005

Depois do descanso...

...pois é, após cerca de 13 dias de paragem por causa de ser o mês de Agosto, com o meu aniversário pelo meio e mais umas quantas ocorrências muito dificilmente iria ter tempo e disponibilidade mental para voltar a pegar nisto.
Da última vez que tinha pegado nisto estava com uns problemas de, ao, utilizar o One-Max, porque raio é que a população (ou melhor, o vector população) não convergia para frequências (estou a usar frequências absolutas) idênticas ao valor da população (estive a experimentar com cromossomas de comprimento 10 e população 40). Estou a fazer o cliente ir buscar um VP (vector-população) ao WS (Web Service), e correr apenas uma iteração do CGA (Compact Genetic Algorithm), de modo, que podia ir acompanhando passo a passo a intercomunicação entre o cliente e o servidor. Aqui um pequeno reparo: ao contrário de pôr o número máximo de iterações a ser executado em cada ciclo de obter/enviar a ser indicado pelo servidor, como era suposto a princípio, estou a fornecer esse limite directo no código do cliente. Por agora, o servidor de WS limita-se a fazer "eco" do VP que o cliente lhe envia, mandando, sem quaisquer alterações, de novo, o VP que tinha acabado de receber. Até agora, ainda não pus mais do que um cliente a correr ao mesmo tempo. Espero vir a fazê-lo em breve, com a ajuda do Multi-Threading de Java.
Mas,como estava dizendo, a dificuldade que vinha tento prendia-se com o facto de a população convergir precocemente antes do que era suposto, por exemplo, para um VP de 10 posições e população de tamanho 40, começa normalmente com:

20;20;20;20;20;20;20;20;20;20

mas depois em vez de dar no fim

40;40;40;40;40;40;40;40;40;40

estava a dar:

20;28;20;36;26;35;19;20;20;32

Achei estranho, e decidi investigar, descobri então, que eram gerados dois indivíduos do vector população, em cada iteração, estavam sempre a ser gerados os mesmos indivíduos a partir do vector população. Tal devia-se ao facto de o gerador de o números aleatórios estar sempre a ser inicializado com a mesma seed, o que fiz para resolver foi pôr uma seed diferente de cada vez que o algoritmo corre, seed essa dada pela hora do sistema, através da função System.currentTimeMillis(). Assim resolveu os problemas, pelo menos, por enquanto. Os meus passos seguintes deverão ser em princípio compreender melhor o Axis, para pôr o WS a devolver dois objectos em vez de apenas um, que é o necessário para se obter não só o VP mas o também o parâmetro m que indica o número de gerações que o cliente deve correr antes de devolver o VP ao servidor.

sexta-feira, agosto 12, 2005

Já entrega...

Enfim, depois de ter dado o passo principal e que consistia em pôr o WS a enviar o vector população "novinho em folha" para o cliente o poder processar para o problema em questão (eu experimentei o OneMax e a calcular o máximo do seno para um intervalo. Em ambos os casos, o cliente processava o vector população completamente até atingir a convergência, ao fim dos quais enviava o vector com a solução para o servidor invocando a função SendPopulationVector, devolvendo um inteiro que indica o estado de sucesso da operação (por enquanto limita-se a devolver 1).
Também, e como já tinha referido no post anterior, os problemas que estou a usar são simples e são resolvidos com poucas iterações. Por exemplo, para os testes que estive a usar, usei um vector de população que representa uma população de 40 indivíduos, cada um com um comprimento de 10 genes. Para o problema One-Max leva 100 gerações, enquanto para encontrar o máximo do seno leva 300. Nada que a minha máquina não resolva numa fracção de segundo.
Para problemas mais sérios terei mais tarde que um número máximo de iterações, o problema é que ainda não consegui descobrir como pôr o WS a devolver não apenas o vector população mas também esse valor, representado por m. É algo que terei que descobrir como se faz, tal como também mandar o vector população como deve ser com uma representação em array adequada de acordo com os standards do SOAP, e não a forma feita em cima do joelho, usando uma string. São ideias para desenvolver mais tarde, por enquanto interessa-me começar a desenvolver o trabalho no sentido de ficar o mais parecido com o que se pretende no enunciado do trabalho, mesmo que esteja implementado com coisas feitas em cima do joelho...

quinta-feira, agosto 11, 2005

Finalmente alguma coisa a funceminar...

Enfim, finalmente e após cerca de três semanas de férias e algumas dores de cabeça consegui desencalhar do ponto de não progressão em que estava também porque nos últimos tempos considerava que também estava de férias de forma que não estava a adiantar nenhum, e por outro lado também tenho ocupado os tempos com o meu vício quando não tenho mais nada para fazer - jogar Warcraft 3.
A minha dificuldade estava em fazer a coisa mais simples possível, que era pôr o Axis a devolver um vector população simples, através do uso de uma função também simples, que devolvia um array de floats e o mandava para o cliente, que a única coisa era simplesmente imprimir depois o conteúdo do vector que recebesse. Claro que estou a proceder ao desenvolvimento e teste na própria máquina (localhost), mas a minha maior dificuldade era a respeito de como transmitir o referido vector população através da rede. Como os Web Services utilizam SOAP para comunicar informação, e é baseado em XML, a dificuldade estava na forma como definir esse vector população de forma a ser transferido usando SOAP, ou seja, de que forma o vector população devia ser codificado em termos de SOAP de forma a ser transmitido efectivamente.
Aqui residia o maior problema, uma vez que o vector de população é um vector de números não inteiros e dessa forma teria de especificar um array quanto muito de double's. Acontece no entanto que o "array de float" não está nos tipos predefinidos que podem ser usados facilmente durante a descrição do serviço através do ficheiro WSDL. Eu julgava que o WSDL fosse a "base de tudo" para começar a definir os serviços a partir daí, mas afinal acabou por não ser assim.

O primeiro ficheiro WSDL que eu defini, que foi feito à "pata", através de exemplos no livro que ando a seguir, e de uns quantos mais, dava sempre erro quando eu tentava fazê-lo passar no WSDL2Java, que gera o código JAVA necessário para a implementação do Web Service de forma imediata tendo por partida apenas o WSDL e estava a usar esta ferramenta para não só gerar o código mas também verificar a síntaxe do WSDL. Acontece que estava sempre a falhar no momento em procedia a este último teste. Fartei-me de fazer aquilo manualmente e acabei por felizmente, após busca na net, um programa em JAVA chamado SOA Editor que permite rapidamente escrever o WSDL sem problemas. Daí a nada, tinha o WSDL que semprei quis ter, e finalmente o WSDL2Java gerou o tão ansiado código que já tinha perdido as esperanças alguma vez de o ver a conseguir obter.
Acontece depois que estive a ler o código gerado e não me agradou muito aquilo que vi, em vez de ser uma coisa simples por onde podia começar, era um código complexo, pronto para usar por pessoas já entendidas no assunto.
Não sabendo o que fazer com aquilo, desisti de usar o WSDL e andei nos últimos 10 dias a tentar encontrar uma solução simples que me permitisse enviar facilmente o vector população.
Sempre achei que o problema devesse estar no array de float's que tinha de definir como um "XML Schema" incorporado dentro do WSDL (no elemento ).
Ou não estava a definir muito bem, porque não percibia muieo disso, ou era o código gerado que não era suficiente esclarecedor. De modo que resolvi o problema da seguinte forma: para poder evitar estar a usar tipos não predefinidos, decidi representar o vector população sob a forma de uma string em que cada elemento do vector é separado do seguinte por ";". Desta forma simplificava a minha vida, e por outro lado, decidi trocar os números decimais por inteiros, uma vez que cada posição do vector população no caso dos números decimais representa a frequência relativa de uma alelo para aquele locus em toda a população, eu podia usar perfeitamente números inteiros, que representavam as frequências absolutas. E, ainda outra simplificação, omiti o parâmetro m, que indica o número de iterações a serem executadas entre cada "envio" do vector população ao servidor. Tudo para bem da simplicidade e da autodidáctica. E no fim, lá consegui, seguindo a par os exemplos patentes no manual do Axis e sem precisar de WSDL nenhum (aliás, o Axis gera-o automaticamente para o caso de ser necessário!) lá consegui finalmente ver o vector população enviado pelo servidor a ser recebido pelo cliente!
Depois pus o cliente a enviar para o servidor o vector população, também o recebia perfeitamente!
Agora o que me falta fazer é começar a pôr cada cliente a trabalhar em cada vector população que lhe é enviado. Começo no entanto a dar com um problema, todos os exemplos simples que tenho tentado, como contar o número de bits a 1 num cromossoma, encontra extremos num intervalo de uma função real de variável real, ou usar "traps", são problemas que se resolver num abrir e fechar de olhos e, de facto, não são nada úteis para testar a potência do trabalho. Tenho que encontrar um problema que seja realmente útil e bastante apelativo e que possa ser resolvido através da aplicação do meu projecto. A questão vai ser encontrá-lo. Mas, por enquanto, importa não pôr a carroça à frente dos bois e vou pensar em pôr tudo o que for Web Services a funcionar! Desejem-me sorte !