Inteligência Artificial Campus Alameda IST @ 007/008 5 de Maio de 008. Introdução O objectivo deste trabalho é desenvolver um solucionador automático em ANSI Common Lisp para o quebra-cabeças Picross. A forma mais interessante de resolver este problema é usar um raciocínio inteligente que analise e propague as restrições do problema (ver secção ). Esta forma de resolução não necessita ou raramente precisa de uma procura por tentativas, dado que a propagação das restrições é suficiente para se determinar a próxima jogada. No entanto, neste projecto o objectivo é usar um raciocínio mais básico (ver secção 3), que não elimine a necessidade de usar procura com alternativas. Devem ser implementadas duas abordagens, ambas baseadas neste raciocínio básico (secção 3), com diferentes funções heurísticas de avaliação de estados e/ou diferentes heurísticas de corte na geração de sucessores. Para resolver problemas mais complexos, o jogador poderá ter que usar alguma forma de raciocínio mais inteligente (secção ), mas nunca um raciocínio que elimine totalmente a necessidade de procura. O objectivo do trabalho é explorar os métodos de procura. Cada grupo deve eleger a sua abordagem preferida para ser comparada com a abordagem preferida dos outros grupos. Os grupos serão ordenados por qualidade dos seus jogadores.. Descrição do quebra-cabeças Picross O quebra-cabeças Picross é um jogo solitário semelhante ao Sudoku, na medida em que também é jogado numa grelha seguindo um conjunto de restrições nas linhas e colunas da tabela. A grelha do Picross tem uma dimensão n x n, em que n pode tomar valores entre 5 e 5. O quebra-cabeças começa com uma grelha vazia e o objectivo é preencher os quadrados, de acordo com as restrições definidas em cada coluna e linha, de modo a formar uma imagem concreta. A lista de números n, n,..., n k que se encontra no topo de cada coluna (números a verde) restringe a forma como cada coluna deve ser preenchida, isto é, dá-nos informação sobre que quadrados devem ser preenchidos na coluna. A coluna deverá ser preenchida, de cima para baixo, por uma sequência de k blocos b, b,..., b k, de tamanho n, n,..., n k, respectivamente, sendo os blocos separados entre si por um ou mais quadrados não preenchidos. Também antes do bloco b e depois do bloco b k poderão ficar quadrados por preencher. As listas de números no topo das colunas podem ter tamanho variado, incluindo zero (lista vazia). Neste caso, nenhum quadrado da coluna deverá ser preenchido. Por sua vez, os números n, n,..., n k que se encontram à esquerda das linhas (números a azul) restringe a forma como cada linha deve ser preenchida, isto é, dá-nos informação sobre que quadrados devem ser preenchidos na linha. A linha deverá ser preenchida, da esquerda para a direita, por uma sequência de k blocos b, b,..., b k, de tamanho n, n,..., n k, respectivamente, sendo os blocos separados entre si por um ou mais quadrados não preenchidos. Também aqui antes do bloco b e depois do bloco b k poderão ficar O jogo Picross foi desenvolvido pela Jupiter e publicado pela Nintendo - http://www.nintendo.com/games/detail/as3-ofdlwnh0lfw-z7gmratluztjlxh
quadrados por preencher. As listas de números à esquerda das linhas podem ter tamanho variado, incluindo zero (lista vazia). Neste caso, nenhum quadrado da linha deverá ser preenchido. A dificuldade deste quebra-cabeças advém do facto de haver vários posicionamentos possíveis dos blocos nas linhas/colunas (dado que os espaços entre blocos não têm tamanho determinado) e haver restrições na direcção ortogonal (colunas/linhas). Convém por isso adoptar uma estratégia que privilegie o preenchimento das linhas/colunas mais restringidas, isto é, aquelas que oferecem menos possibilidades ao posicionamento dos blocos. Convém também deduzir que quadrados terão forçosamente que ficar preenchidos e ficar por preencher. Desta forma, vai-se sucessivamente aumentando as restrições ao preenchimento da direcção ortogonal e ajudando a determinar a solução do problema. 3. Um exemplo de resolução Abordagem mais básica Para facilitar a compreensão do quebra-cabeças, a seguir demonstra-se como se preencheria uma grelha de 5 x 5. Suponha que o jogo começa com a grelha vazia com as seguintes restrições: 5 3 3 De entre todas as linhas e colunas, a que tem o preenchimento mais restringido é a segunda coluna. O número 5 no topo da coluna diz-nos que temos de preencher a coluna com um único bloco de 5 quadrados. Como o tamanho da coluna é 5, isto significa que a coluna deve ser toda preenchida, não havendo qualquer possibilidade de variação: 5 3 3
Não há mais nenhuma coluna cujo preenchimento esteja determinado. Por exemplo, a quinta coluna, tem apenas um bloco de tamanho, mas dado que a coluna tem tamanho 5, existem duas possibilidades de preenchimento, uma nas linhas,, 3 e e outra nas linhas, 3, e 5. No entanto, o preenchimento de uma coluna impõe restrições ao preenchimento de todas as linhas que intersectam os quadrados da coluna já preenchidos bem como os quadrados da coluna que já se sabe que não podem ser preenchidos. Assim, o preenchimento da segunda coluna impôs restrições adicionais ao preenchimento de todas as linhas. Mais uma vez, devemos começar pela linha mais restringida, neste caso a segunda. Os números 3 e à sua esquerda significam que temos de prencher a linha com dois blocos, de 3 e quadrados respectivamente, separados de pelo menos um quadrado. Como a linha é de tamanho 5, a única solução é preencher os primeiros 3 quadrados (a contar da esquerda), depois deixar um espaço em branco e, finalmente, preencher mais um quadrado. Este preenchimento é perfeitamente compatível com o preenchimento da segunda coluna já preenchida e, portanto, não coloca qualquer problema na busca de uma solução. 5 3 3 Um quadrado que temos a certeza que já não poderá ser preenchido deve ser marcado como tal, de forma a não cometermos o erro de o tentar preencher mais tarde (neste caso marcado a creme). Esta informação visual também explicita uma restrição adicional ao preenchimento da quarta coluna. De facto, com esta informação, podemos seguramente concluir que a quarta coluna, com o número 3 verde no topo, será preenchida da seguinte maneira: 5 3 3 3
Como o quadrado creme não pode ser preenchido (se fosse a segunda linha ficava incorrectamente preenchida de acordo com a sua informação à esquerda) e o número diz-nos que temos de preencher 3 quadrados sucessivos na vertical, esta é a única solução possível. Esta é outra das razões porque convém marcar os quadrados que não podem ser preenchidos. Também pelo facto da quarta coluna só ter um bloco, podemos concluir que o quadrado da primeira linha também não pode ser preenchido, sendo marcado a creme. Se olharmos para a última linha vemos que há apenas uma solução possível, isto é, temos de preencher dois quadrados, deixar um espaço (porque neste caso a linha é de tamanho 5) e depois preencher dois quadrados: 5 3 3 O preenchimento desta linha resolveu a primeira coluna ( ) e determinou o preenchimento da última coluna () e, consequentemente, da terceira () e da quarta () linhas dado que, como têm que ter quatro quadrados seguidos, há apenas uma única solução possível: 5 3 3 Mais uma vez se pintaram de creme os quadrados que não podem ser preenchidos. Resta-nos preencher o único quadrado livre para resolver simultaneamente a primeira linha e a terceira coluna:
5 3 3 Com isto acabámos de preencher todos os quadrados possíveis para esta grelha! Se repararmos com atenção (e um pouco de imaginação e boa vontade ) esta figura representa um cão. Todas as grelhas disponibilizadas resultam numa imagem concreta e não abstracta.. O mesmo exemplo de resolução Abordagem mais inteligente Este exemplo é muito simples pois não há muitas possibilidades para o posicionamento dos blocos. No entanto, à medida que o tamanho das linhas/colunas vai aumentando, o número de possibilidades normalmente aumenta. Nestes casos, embora não seja possível determinar de imediato o preenchimento total das linhas/colunas, é ainda assim possível determinar o seu preenchimento parcial. Por exemplo, embora no início não seja possível determinar de imediato o preenchimento da terceira coluna, poder-se-ia determinar o seu preenchimento parcial, dado que em qualquer das duas possibilidades de preenchimento (linhas,, 3 e ou linhas, 3, e 5) as linhas, 3 e ficarão necessariamente preenchidas: 5 3 3 De facto, logo no início do problema, e usando uma lógica idêntica para todas as colunas, poder-se-ia ter preenchido a grelha da seguinte forma: 5
5 3 3 Usando uma lógica idêntica para as linhas, poder-se-ia ter preenchido a grelha da seguinte forma: 5 3 3 Juntando as deduções para as colunas e linhas (fazendo a união dos dois preenchimentos anteriores), poderse-ia ter preenchido logo de início a grelha da seguinte forma: 5 3 3 6
Este preenchimento corresponde à solução do problema, desta forma encontrada muito mais rapidamente. Por outras palavras, usando deduções mais inteligentes pode-se acelerar a procura da solução. Em problemas mais complexos, é a única forma de procurar uma solução sem se ter que estudar todas as possíveis alternativas de resolução distintas. Normalmente, o problema não é resolvido desta forma, isto é, não se tenta preencher todas as linhas e colunas de forma indistinta. Em vez disso, preenche-se uma linha/coluna de cada vez, escolhendo em cada momento a mais restringida, e aplicando de seguida esta esta lógica para a linha/coluna seleccionada. 5. Descrição da interface O conjunto de funções que implementa o jogo deve ser definido num único ficheiro, o qual deve poder ser compilado sem erros nem avisos. 5.. Função faz-picross e função faz-picross-lento Devem ser implementadas as funções faz-picross e faz-picross-lento, as quais permitem criar dois jogadores automáticos, um rápido e um mais lento, que sabem jogar Picross. Ambas as funções recebem como argumentos: a dimensão n x n da grelha (que pode assumir os valores 5, 0 e 5) os valores horizontais (nested lists): que afectam as linhas da grelha. os valores verticais (nested lists): que afectam as colunas da grelha e retornam um jogador automático. Este jogador é uma função que recebe como argumento as dimensões da grelha, os valores horizontais e verticais actuais e retorna um dos sucessores possíveis dessa grelha, isto é, a grelha para onde o jogador automático deve jogar. No caso de a grelha representar um jogo já acabado o jogador deve retornar NIL. O exemplo seguinte mostra a utilização da função faz-picross para criar um jogador: > (setf jogador (faz-picross 5 5 ( (5 5) (0) ( 3 5)... ) ( (5 5) (0) ( 3 5)... ) )) #<Interpreted Function (unnamed) @ #x8b633> Este exemplo, serve também para a função faz-picross-lento e é meramente ilustrativo, não pretende ser uma grelha real. Na secção estão os exemplos que devem usar para experimentar o vosso programa. A forma como representam a grelha inicial, intermédias e final devem respeitar a representação detalhada na secção 5.. 5.. Representação do grelha usada na interface A representação de uma casa da grelha depende do seu conteúdo: se for um quadrado preenchido :P se for um quadrado a branco :B se for um quadrado que não se pode preencher :* Uma grelha é representada por uma lista cujos elementos são sublistas que contêm peças e representam as linhas do tabuleiro. Por exemplo, a grelha 7
5 3 3 é representada pela seguinte lista: ((:B :P :B :B :B) (:P :P :P :* :P) (:B :P :B :B :B) (:B :P :B :B :B) (:B :P :B :B :B)) 6. Implementação Dado o elevado factor de ramificação do problema, devem ser estudadas e implementadas estratégias de limitação de sucessores que permitam aumentar a capacidade do jogador automático. Deve-se definir pelo menos o tipo abstracto de informação grelha. Uma possibilidade para aumentar a eficiência é fazer com que o jogador automático traduza a grelha que recebe numa outra representação mais económica, de seguida use a grelha nessa representação e, finalmente, a traduza de volta para a representação requerida pela interface. Sugere-se que o programa seja feito por etapas. É aconselhável que, numa primeira etapa, se implemente os operadores utilizando a representação das grelhas descrita na secção anterior e um método de procura cega. Estando isto a funcionar correctamente, deve-se então passar às etapas seguintes em que se devem explorar novos métodos de procura e diferentes heurísticas. Finalmente, deve-se pensar em termos de eficiência optimização a representação da grelha e tudo o resto. Cada chamada ao jogador automático deve ser feita num ambiente Lisp novo, para evitar que sejam introduzidos erros na medição do tempo. 7. Campeonato Com o intuito de estimular a eficiência do código entregue, vai-se realizar um campeonato entre os vários jogadores automáticos. Os jogadores vão ser testados com uma grelha de 5 x 5, outra de 0 x 0 e finalmente uma de 5 x 5, definidas pelo corpo docente e as quais serão disponibilizado quando sairem as notas do projecto. 8
O vencedor do campeonato tem uma bonificação de valor na nota final da cadeira. O segundo classificado tem uma bonificação de 0,5 valores na nota final. O terceiro classificado tem uma bonificação de 0,3 valores na nota final. Para evitar incompatibilidades entre os vários jogadores no campeonato, cada jogador vai ser carregado e chamado num ambiente LISP novo. 8. Critérios de avaliação A avaliação vai ser feita com base nos seguintes parâmetros: Estudo desenvolvido sobre o problema, incluindo funções de avaliação heurística e heurísticas de corte testadas e estudo comparativo das mesmas, problemas surgidos e formas de os resolver (0%); Execução correcta (30%); Qualidade do jogador (0%); Apreciação global (0%). A qualidade do jogador será baseada nos seguintes factores: - tempo de resolução do jogo; - número de nós expandidos desde a primeira jogada até a grelha estar totalmente preenchida; - número total de jogadas. Estes valores terão que ser escritos no ecrã pelo jogador após encontrar uma solução. 9. Inscrições e entrega do projecto Os elementos de cada grupo, que deverão ser no máximo, devem inscrever-se no Fénix de acordo com as instruções a divulgar oportunamente na página da cadeira. A entrega será feita até às 5h00 do dia de Junho de 008 da seguinte forma: o ficheiro com o jogador automático e o relatório em formato electrónico (ficheiro em formato pdf ou alternativamente em formato word) deve ser entregue de forma electrónica de acordo com instruções a publicar na página da cadeira; o relatório em papel (incluindo a listagem do programa devidamente paragrafada e utilizando um tipo de letra mono-espaçado) deve ser entregue na reprografia do DEI tendo como capa a última folha deste enunciado devidamente preenchida. Todo o material entregue pelos alunos (documentação e ficheiro com o código do jogador automático) deve conter a identificação do grupo (número do grupo, fornecido durante a inscrição do grupo) e o número e nome de cada elemento do grupo. Entregas realizadas após as 5h00 do dia de Junho de 008 são penalizadas da seguinte forma: até 30 minutos de atraso a penalização é de 0,5 valores; de 30 minutos a horas de atraso a penalização é de valor; de horas a horas de atraso a penalização é de 3 valores; a partir de horas de atraso não são aceites quaisquer projectos. 9
0. Novidades do projecto No caso de haver novidades relativas ao projecto, estas serão afixadas na página da cadeira pelo que esta página deve ser visitada diariamente. Serão publicados mais exemplos de grelhas na página da cadeira.. Exemplo de grelhas Exemplo de grelhas que devem ser resolvidas com o programa desenvolvido: Exemplo : - Valores Horizontais: (() (3 6) (8) (3 6) () () (3 ) (0) (3 ) ()) - Valores Verticais: ((3 3) (3 3) (3 3) ( ) (3 3) (3 3) (3 3) (3 5) ( ) ( )) Exemplo : - Valores Horizontais: (() () ( ) ( ) ( ) ( ) ( ) ( ) ( ) ()) - Valores verticais: (( ) ( ) (6) ( ) ( 3 ) ( ) ( ) ( ) () (3)) Exemplo 3: - Valores Horizontais: (() ( ) ( 3 ) ( ) ( ) ( ) ( ) ( 3 ) ( ) ()) - Valores Verticais: (() ( ) ( ) ( ) (6) (8) ( ) ( ) ( ) (6)) Exemplo : - Valores Horizontais: ((3) (3 ) (3 ) ( ) ( ) ( 3) ( 6) ( ) (3) (3)) - Valores Verticais: ((3) (3) ( ) ( 3 ) ( ) ( ) ( 3) ( 3) ( 3) (3)) Exemplo 5: - Valores Horizontais: (() ( ) (3 3) ( ) ( 5 ) ( ) ( ) ( 6) ( ) ( )) - Valores Verticais: ((3) (3 ) ( ) ( ) (3 ) ( ) ( ) ( 3 ) ( ) ()) Nota: O simbolo (), significa que essa linha ou coluna já estão preenchidas. 0
Inteligência Artificial Campus Alameda Projecto (007/008) Número do grupo (obtido a partir do sistema Fénix): Nome: Número: Nome: Número: Nome: Número: Soma das horas gastas exclusivamente para fazer este trabalho: Limite para entrega: dia 0/06/008, às 5 horas.