Projeto de Programação 2
Sokoban - 倉庫番

Universidade Federal do ABC
MCZA020-13 - Programação Paralela
2020.Q1

Professor: Emilio Francesquini
E-mail: e.francesquini@ufabc.edu.br

Data limite: 07/06/2020 \(\to\) 20/06/2020


Índice


1 Introdução

Sokoban (倉庫番, sōkoban, zelador do armazém) é um videogame criado em 1981 por Hiroyuki Imabayashi e publicado em 1982 pela empresa Thinking Rabbit.

sokoban_ani.gif

Figura 1: Sokoban (Fonte: Wikipedia)

Neste jogo o jogador deve organizar algumas caixas pelo tabuleiro de modo que ao final haja uma caixa sobre cada uma das casas-alvo. O tabuleiro, cuja dimensão varia conforme a fase, é dividido em casas quadradas que podem ser apenas um elemento dentre os seguintes:

  • Casa vazia (que pode ser uma casa-alvo ou não)
  • Parede
  • Caixa
  • Jogador


Para organizar as caixas o jogador pode se deslocar em 4 direções (acima, abaixo, esquerda e direita) e empurrar as caixas. Ele não pode, contudo, puxar caixas. Logo, se uma caixa estiver em um canto ela não pode ser mais movida. Além disto apenas uma caixa pode ser movimentada por vez.


O objetivo principal é, obviamente, resolver o quebra cabeça. O objetivo secundário é resolvê-lo utilizando o menor número possível de movimentos.

sokoban-dos.jpg

Figura 2: Sokoban para DOS (1984)

2 O projeto

A criação de um programa que soluciona uma fase de Sokoban é muito mais complicada do que pode parecer. Em particular, o problema é NP-Difícil e PSPACE-completo1. Como o custo computacional de resolver uma das fases do Sokoban na força bruta pode ser proibitivamente caro, ultimamente tem havido uma série de tentativas de aplicar técnicas de inteligência artificial para diminuir o tempo para encontrar uma solução2.


Neste projeto vamos tomar um caminho diferente: se na força bruta e no martelo não dá para resolver, vamos usar uma marreta.

chapo.jpg

Figura 3: Já que é pra falar das coisas antigas, o Chapolin Colorado (década de 70) já sabia sobre os poderes de uma marretada…

Ao contrário daquelas abordagens nós vamos continuar a tentar resolver o puzzle na força bruta mas, em lugar de ser apenas um thread/processo, vamos utilizar um número arbitrário de threads.


O projeto tem 2 objetivos, um de implementação e outro de avaliação.

Quanto a implementação, neste você deverá implementar duas versões paralelas de um solver força bruta. A primeira deverá utilizar Pthreads e segunda utilizar OpenMP para paralelização. Se desejarem vocês podem utilizar memória transacional na implementação que utiliza Pthreads caso isso facilite a sua vida.

Sugiro que utilizem a linguagem de programação C ou C++ já que são oficialmente (a menos que queiram usar Fortran) as linguagens que o GCC tem suporte para OpenMP.

O segundo objetivo é analizar o desempenho das implementações apresentadas. Observe como o speedup e a eficiência variam com a adição de processadores e com a entrada do problema. Lembre-se de avaliar o comportamento da sua aplicação utilizando ferramentas como perf stat e perf top.


Você pode se basear no código sequencial de outros3, mas é obrigatório indicar claramente no seu relatório e em comentários no seu código a origem do código fonte. O código paralelo utilizando Pthreads e OpenMP, contudo, deve ser obrigatoriamente de sua própria autoria. 4

2.1 Entrada

A entrada do seu programa será dada por um arquivo contendo a fase a ser resolvida e o número de threads a utilizar (além do main thread). Você pode baixar aqui um conjunto com as 90+2 fases (que serão utilizadas durante a correção). As fases 01 a 90 são as fases clássicas do jogo e as fases -1 e 00 são fases artificialmente simples que são úteis para testar o seu código.


Os arquivos utilizam a seguinte notação (cada caractere é uma casa do tabuleiro):

  • Casas vazias são representadas por espaços
  • # (sustenido) representa uma parede
  • $ (sifrão) indica a presença de uma caixa
  • . (ponto) é uma casa-alvo
  • * (asterisco) é caixa sobre uma casa-alvo
  • @ (arroba) é o Sokoban
  • + (sinal de adição) é o Sokoban em uma casa-alvo


Veja o do arquivo de entrada level01 abaixo:

    #####
    #   #
    #$  #
  ###  $##
  #  $ $ #
### # ## #   ######
#   # ## #####  ..#
# $  $          ..#
##### ### #@##  ..#
    #     #########
    #######

E uma versão gráfica gerada pelo XSok da fase acima:

xsok.png

As fases 01-90 disponibilizadas no arquivo acima são as mesmas disponíveis no XSok utilizando o Level Subset → Sokoban. Para instalar o XSok basta fazer:


sudo apt-get install xsok


ou o equivalente da sua distribuição Linux.

2.2 Saída

A saída do seu programa deve consistir na sequência de movimentos feitos pelo Sokoban para resolver a fase dada como entrada. O formato da saída é o seguinte (formato LURD):

  • u - Cima (up)
  • d - Baixo (down)
  • l - Esquerda (left)
  • r - Direita (right)
  • U - Cima com movimentação de caixa (up)
  • D - Baixo com movimentação de caixa (down)
  • L - Esquerda com movimentação de caixa (left)
  • R - Direita com movimentação de caixa (right)


Arquivo level_00:

#######
#     #
#     #
#. #  #
#. $$ #
#.$$  #
#.#  @#
#######


Exemplo de execução ($ indica o prompt do terminal):

$ ./meu_sokoban level00 4
ulULLulDDurrrddlULrruLLrrUruLLLulD
$


ATENÇÃO Seu programa deve ser capaz de resolver pelo menos os níveis -1, 00 e 01 (seu programa será executado em uma máquina com pelo menos 16GB de RAM). Programas que não forem capazes de resolver o nível 01 sofrerão uma redução significativa na nota.

As execuções de teste serão feitas em máquinas paralelas com até 16 processadores (\(1 \le P \le 16\)).


3 Entregas e avaliação

Todos as entregas descritas abaixo devem ser feitas através do GitHub Classroom.

Link para inscrição: https://classroom.github.com/a/X_-y3_Of

3.1 Código (4 pontos)

  • Você deve entregar todo o código fonte do seu programa juntamente com instruções claras sobre sua compilação e execução.
  • Programas com erros de compilação receberão nota 0.
  • O ambiente de testes será Linux com GCC. Você deve entregar uma versão sequencial do seu código além da versão paralelizada com Pthreads e OpenMP. Lembre-se: aqui estamos interessados na versão força bruta do problema, e não em uma solução que envolva a aplicação de conceitos avançados de IA.
  • Programas que não cumprirem os requisitos (resultados incorretos, erros durante a execução, …) descritos na seção anterior receberão nota 0.
  • Programas sem boa documentação no código terão a sua nota reduzida.
  • Programas desorganizados (nomes de variáveis/funções ruins, falta de identação, …) terão a sua nota reduzida.

3.2 Relatório (3 pontos)

Juntamente com o seu código você deverá entregar um relatório (máximo de 4 páginas) que contenha:

  • Fases resolvidas: Solução, tempo para resolver, máquina utilizada e número de threads utilizado.
  • Uma explicação detalhada de como o particionamento das tarefas que foi feito entre os threads na sua implementação.
  • Tabelas e gráficos do speedup e da eficiência para pelo menos as fases 00 e 01 com \(1 \le P \le 16\) (não esqueça de incluir a especificação da máquina utilizada para a execução
  • Interpretação dos valores mostrados na tabela anterior. Descreva e interprete a variação do speedup e da eficiência em relação à \(P\). Explique os resultados obtidos levando em consideração as características da máquina utilizada.
  • Análise da escalabilidade da sua implementação. Ela é escalável? Apresenta escalabilidade forte ou fraca?
  • Análise do consumo de memória da sua implementação.
  • Análise do balanceamento de carga. Todos os threads recebem a mesma quantidade de trabalho? Todos acabam a execução aproximadamente ao mesmo tempo?


Dica: Utilize como modelo para a sua análise as seções 3.6.2, 3.6.3 e 3.6.4 do livro [PP].


Obs.: Certifique-se de executar o seu programa pelo menos 3 vezes e relate o tempo da execução mais rápida (wall-clock time). Veja a motivação para fazê-lo nas notas de aula e/ou no livro [PP]-Cap. 3.

3.3 Desempenho (3 pontos)

  • É esperado que você consiga speedup > 1 na versão paralela.
  • O teste de desempenho será efetuado em uma máquina Intel Xeon E5 com 16 cores (32 threads) com 64 GB de RAM.

3.4 Bônus 1 (+1 ponto)

O programa que tiver o melhor speedup dentre os entregues receberá 1 ponto adicional na avaliação.

3.5 Bônus 2 (+1 ponto)

Caso o seu código execute mais rapidamente que o código do professor ou caso ele seja o mais rápido da turma.

3.6 Política de atrasos

Projetos entregues com atraso sofrerão uma redução da nota conforme a tabela abaixo:

Dias em Atraso Nota Máxima
0 10
1 7
2 6
3 5
>3 0

Notas de Rodapé:

1

Dor, Dorit, and Uri Zwick. ”SOKOBAN and other motion planning problems.” Computational Geometry 13.4 (1999): 215-228. https://doi.org/10.1016/S0925-7721(99)00017-6

2

Veja https://arxiv.org/abs/1807.00049 para mais informações

3

Soluções sequenciais do Sokoban não faltam na internet. Veja por exemplo https://rosettacode.org/wiki/Sokoban

Autor: Emilio Francesquini

Criado em: 2020-06-01 seg 19:17