Ferramentas de Utilizador

Ferramentas de Site


inf05016:2014-2-trabalhos

Diferenças

Esta página mostra as diferenças entre as duas revisões da página.

Ligação para esta vista de comparação

Próxima revisão
Revisão anterior
inf05016:2014-2-trabalhos [2014/08/06 13:04]
marcus Criação deste novo documento.
inf05016:2014-2-trabalhos [2014/11/05 13:40] (Actual)
marcus [Trabalho 4 (Segmentação de imagens)]
Linha 1: Linha 1:
 ==== Trabalho 1 (Heaps binários) ==== ==== Trabalho 1 (Heaps binários) ====
  
-Entrega: 18/09/2014+Entrega: 18/08/2014
  
 === Objetivos === === Objetivos ===
Linha 8: Linha 8:
   * Implementar o algoritmo de Dijkstra usando o heap implementado.   * Implementar o algoritmo de Dijkstra usando o heap implementado.
   * Comparar a complexidade teórica pessimista com a complexidade real. Em particular verificar que a complexidade real respeita o limite teórico.   * Comparar a complexidade teórica pessimista com a complexidade real. Em particular verificar que a complexidade real respeita o limite teórico.
 +  * Avaliar o escalonamento do algoritmo Dijkstra. 
 + 
 === Casos de teste === === Casos de teste ===
  
-  * caso de teste é o rede de trânsito de New York, que pode ser baixado na [[http://​www.dis.uniroma1.it/​~challenge9/​download.shtml|página do DIMACS challenge]]. +  * Verificação da complexidade das operações:​ gerar casos de testes via um programa. 
-  * Para testar: Gerar um número suficiente (>100) de pares aleatórias de vértices origem e destino e medir o tempo de execução e o número de operações "​insert",​ "​deletemin"​ e "​decreasekey"​.+  * Verificação da complexidade do Dijkstra: usar o gerador de casos de testes abaixo.  
 +  * Verificação do escalonamento:​ o caso de teste é o rede de trânsito de New York e dos EUA (distance), que pode ser baixado na [[http://​www.dis.uniroma1.it/​~challenge9/​download.shtml|página do DIMACS challenge]]. 
 +  * Para testar ​em geral: Gerar um número suficiente (>30) de pares aleatórias de vértices origem e destino e medir o tempo de execução e o número de operações "​insert",​ "​deletemin"​ e "​decreasekey"​.
  
 === Observações === === Observações ===
Linha 97: Linha 100:
 </​code>​ </​code>​
  
 +=== Leitura (Exemplo) ===
 +<code c++>
 +void read_dimacs(std::​istream&​ in, unsigned&​ n, unsigned&​ m, MyGraph&​ a) {
 +  std::string line="",​ dummy;
 +  while (line.substr(0,​4) != "p sp")
 +    getline(in,​line);​
 +
 +  // (1) get nodes and edges
 +  std::​stringstream linestr;
 +  linestr.str(line);​
 +  linestr >> dummy >> dummy >> n >> m;
 +  a.resize(n);​
 +  unsigned i=0;
 +  while (i<m) {
 +    getline(in,​line);​
 +    if (line.substr(0,​2) == "a ") {
 +      std::​stringstream arc(line);
 +      unsigned u,v,w;
 +      char ac;
 +      arc >> ac >> u >> v >> w;
 +      // processar arco (u,v) com peso w
 +      i++;
 +    }
 +  }
 +}
 +</​code>​
 +
 +==== Trabalho 2 (Heaps de Fibonacci) ====
 +
 +Entrega: 01/09/2014
 +
 +=== Objetivos ===
 +
 +  * Implementar duas variantes de um heap de Fibonacci: i) a tradicional,​ com corte em cascata de acordo com a "​marca"​ do vértice, ii) a randomizada.
 +  * Verificar a complexidade das operações experimentalmente.
 +  * Implementar o algoritmo de Dijkstra usando o heap implementado.
 +  * Comparar a complexidade teórica pessimista do algoritmo de Dijkstra com a complexidade real usando as duas variantes do heap de Fibonacci. Em particular verificar que a complexidade real respeita o limite teórico.
 +  * Comparar a complexidade com aquela do heap binário.
 +
 +=== Casos de teste ===
 +
 +  * Os mesmos do trabalho 1.
 +
 +=== Observações ===
 +
 +  * A variante randomizada de um heap de Fibonacci está descrita em [[http://​arxiv.org/​abs/​1407.2569|Li,​Peebles,​Replacing Mark Bits with Randomness in Fibonacci Heaps]]. O método a) Continua um corte em cascata com probabilidade 1/2 e não usa "​marcas"​. b) Reconstrói o heap em cada operação com probabilidade 1/n. A reconstrução insere todas chaves do heap atual num heap novo.
 +
 +=== Convenções ===
 +  * As mesmas do trabalho 1.
 +
 +==== Trabalho 3 (Fluxo s-t máximo) ====
 +
 +Entrega: 18/09/2013.
 +
 +=== Objetivos ===
 +  * Implementar o algoritmo push-relabel.
 +  * Verificar a complexidade do algoritmo experimentalmente e comparar com a complexidade teórica O(n^3) e com o algoritmo do trabalho 2.
 +=== Casos de teste ===
 +  * Um gerador de casos de teste em formato DIMACS em C é disponível {{http://​www.inf.ufrgs.br/​~mrpritt/​aa/​washington.c|aqui}}.
 +  * Documentação:​
 +<​code>​
 +             To use:  cc washington.c -o gengraph
 +                      gengraph function arg1 arg2 arg3
 +
 +             ​Command line arguments have the following meanings:
 +
 +                      function: ​          index of desired graph type
 +                      arg1, arg2, arg3:   ​meanings depend on graph type
 +                                          (briefly listed below: see code
 +                                           ​comments for more info)
 +
 +                 Mesh Graph: ​         1 rows  cols  maxcapacity
 +                 ​Random Level Graph: ​ 2 rows  cols  maxcapacity
 +                 ​Random 2-Level Graph:3 rows  cols  maxcapacity
 +                 ​Matching Graph: ​     4 vertices ​ degree
 +                 ​Square Mesh:         5 side  degree ​ maxcapacity
 +                 Basic Line:          6 rows  cols  degree
 +                 ​Exponential Line:    7 rows  cols  degree
 +                 ​Double Exponential ​  8 rows  cols  degree
 +                 ​DinicBadCase: ​       9 vertices
 +                      (causes n augmentation phases)
 +                 ​GoldBadCase ​        10 vertices
 +                 ​Cheryian ​           11 dim1 dim2  range
 +                      (last 2 are bad for goldberg'​s algorithm)
 +</​code>​
 +
 +^ No. ^ Nome ^ Parâmetros ^ Descrição ^ n ^ m ^
 +|   1 | Mesh | r,c | Grade, 3 viz. 1 direita | rc+2 | 3r(c-1) |
 +|   2 | Random level | r,c | Grade, 3 viz. rand. 1 direita | rc+2 | 3r(c-1) |
 +|   3 | Random 2-level | r,c | Grade, 3 viz. rand. 2 direita | rc+2 | 3r(c-1) |
 +|   4 | Matching | n,d | Bipart. n-n, d viz. rand. | 2n+2 | n(d+2) |
 +|   5 | Square Mesh | d,D | Quadr. mesh dxd, grau D | d*d+2 | (d-1)dD+2d |
 +|   6 | BasicLine | n,m,D | Linha, grau D| nm+2 | nmD+2m |
 +|   7 | ExpLine | n,m,D | Linha, grau D | nm+2 | nmD+2m |
 +|   8 | DExpLine | n,m,D | Linha, grau D | nm+2 | nmD+2m |
 +|   9 | DinicBad | n | Linha | n | 2n-3|
 +|  10 | GoldBad | n | | 3n+3 | 4n+1 |
 +
 +=== Convenções ===
 +  * As implementações do algoritmo devem aceitar uma instância no formato {{http://​lpsolve.sourceforge.net/​5.5/​DIMACS_maxf.htm|DIMACS}} na entrada padrão (stdin) e imprimir o valor do fluxo máximo na saída padrão (stdout).
 +
 +=== Verificação ​ ===
 +  * O seguinte código determina o fluxo máximo. Para compilar: Usar C++ e {{http://​www.boost.org|Boost}}.
 +<code c++>
 +/**
 + * \file maxflow.cpp
 + ​* ​  ​\author Marcus Ritt <​mrpritt@inf.ufrgs.br>​
 + ​* ​  ​\version $Id: emacs 2872 2009-01-31 01:46:50Z ritt $
 + ​* ​  \date Time-stamp: <​2009-03-23 17:52:25 ritt>
 + *
 + * Read a maximum flow problem in DIMACS format and output the maximum flow.
 + *
 + */
 +#include <​iostream>​
 +#include <​cstring>​
 +using namespace std;
 + 
 +#include <​boost/​graph/​adjacency_list.hpp>​
 +#include <​boost/​graph/​read_dimacs.hpp>​
 +#include <​boost/​graph/​edmonds_karp_max_flow.hpp>​
 +using namespace boost;
 +
 +// graph element descriptors
 +typedef adjacency_list_traits<​vecS,​vecS,​directedS>::​vertex_descriptor DiNode;
 +typedef adjacency_list_traits<​vecS,​vecS,​directedS>::​edge_descriptor Edge;
 +
 +typedef unsigned Capacity;
 +struct VertexInformation {};
 +struct EdgeInformation {
 +  Capacity edge_capacity;​
 +  Capacity edge_residual_capacity;​
 +  Edge reverse_edge;​
 +};
 + 
 +typedef adjacency_list<​vecS,​vecS,​directedS,​VertexInformation,​EdgeInformation>​ DiGraph;
 + 
 + 
 +int main(int argc, char *argv[]) {
 +  // (0) read graph
 + 
 +  DiGraph g;
 +  DiNode s,t;
 + 
 +  read_dimacs_max_flow(g,​
 +                       ​get(&​EdgeInformation::​edge_capacity,​g),​
 +                       ​get(&​EdgeInformation::​reverse_edge,​g),​
 +                       s, t);
 + 
 +  // (1) determine maximum flow
 +  cout << edmonds_karp_max_flow(g,​ s, t,
 +                                capacity_map(get(&​EdgeInformation::​edge_capacity,​g)).
 +                                residual_capacity_map(get(&​EdgeInformation::​edge_residual_capacity,​g)).
 +                                reverse_edge_map(get(&​EdgeInformation::​reverse_edge,​g))) << endl;
 +}
 +</​code>​
 +
 +==== Trabalho 4 (Segmentação de imagens) ====
 +
 +Entrega: 29/09/2014
 +
 +=== Objetivos ===
 +  * Implementar um algoritmo de segmentação de imagens como vista em aula.
 +  * Usar a própria implementação do fluxo máximo na solução.
 +  * Segmentar uma imagem em pele/​não-pele com pesos de separação diferentes.
 +  * Relatar o tempo de processamento & apresentar diferentes segmentações.
 +
 +=== Casos de teste ===
 +  * O caso de teste é uma imagem de si mesmo.
 +
 +=== Convenções ===
 +  * As implementações do algoritmo devem aceitar uma imagem no formata PPM plain na entrada padrão (stdin) e imprimir uma imagem no mesmo formato (com todos pixels não-pelo em preto) na saída padrão (stdout).
 +
 +=== Códigos disponíveis ===
 +  * Ler uma imagem PPM plain
 +<code c++>
 +// image data structure
 +enum { R = 0, G, B };
 +typedef unsigned short Color;
 +typedef multi_array<​Color,​3>​ Image;
 +
 +// read an image im PPM (plain) format
 +void read_ppm(Image&​ im, istream&​ in) {
 +  unsigned w,​h,​maxcolor;​
 +  string magic;
 +  ​
 +  in >> magic >> w >> h >> maxcolor;
 +  assert(magic == "​P3"​);​
 +  ​
 +  im.resize(extents[h][w][3]);​
 +  ​
 +  for(unsigned i=0; i<h; i++)
 +    for(unsigned j=0; j<w; j++)
 +      in >> im[i][j][R] >> im[i][j][G] >> im[i][j][B];​
 +}
 +</​code>​
 +
 +  * Imprimir uma imagem PPM plain
 +<code c++>
 +  cout << "P3 " << w << " " << h << " 255 " << endl;
 +  for(unsigned i=0; i<h; i++) {
 +    for(unsigned j=0; j<w; j++)
 +      cout << im[i][j][R] << " " << im[i][j][G] << " " << im[i][j][B] << " ";
 +      cout << endl;
 +  }
 +</​code>​
 +  * Converter qualquer imagem para PPM plain (usando {{http://​www.imagemagick.org|Image Magick}})
 +<​code>​
 +  convert -compress none myimage.ext myimage.ppm
 +</​code>​
 +
 +  * Determinar a probabilidade de pele ou não-pele (para obter valores inteiros multiplicar com p.ex. 10.000.000.000)
 +<code c++>
 +// mixture of Gaussians, according to Jones, Regh
 +const unsigned nG = 16;
 +const unsigned nV = 7;
 +double skin[nG][nV] = {
 + { 73.53, 29.94, 17.76, ​ 765.40, 121.44, 112.80, 0.0294 },
 + { 249.71, 233.94, 217.49, ​ 39.94, 154.44, 396.05, 0.0331 },
 + { 161.68, 116.25, 96.95, ​ 291.03, 60.48, 162.85, 0.0654 },
 + { 186.07, 136.62, 114.40, ​ 274.95, 64.60, 198.27, 0.0756 },
 + { 189.26, 98.37, 51.18, ​ 633.18, 222.40, 250.69, 0.0554 },
 + { 247.00, 152.20, 90.84, ​ 65.23, 691.53, 609.92, 0.0314 },
 + { 150.10, 72.66, 37.76, ​ 408.63, 200.77, 257.57, 0.0454 },
 + { 206.85, 171.09, 156.34, ​ 530.08, 155.08, 572.79, 0.0469 },
 + { 212.78, 152.82, 120.04, ​ 160.57, 84.52, 243.90, 0.0956 },
 + { 234.87, 175.43, 138.94, ​ 163.80, 121.57, 279.22, 0.0763 },
 + { 151.19, 97.74, 74.59, ​ 425.40, 73.56, 175.11, 0.1100 },
 + { 120.52, 77.55, 59.82, ​ 330.45, 70.34, 151.82, 0.0676 },
 + { 192.20, 119.62, 82.32, ​ 152.76, 92.14, 259.15, 0.0755 },
 + { 214.29, 136.08, 87.24, ​ 204.90, 140.17, 270.19, 0.0500 },
 + { 99.57, 54.33, 38.06, ​ 448.13, 90.18, 151.29, 0.0667 },
 + { 238.88, 203.08, 176.91, ​ 178.38, 156.27, 404.99, 0.0749 }
 +};
 +
 +double noskin[nG][nV] = {
 + { 254.37, 254.41, 253.82, ​ 2.77, 2.81, 5.46, 0.0637 },
 + { 9.39, 8.09, 8.52,  46.84, 33.59, 32.48, 0.0516 },
 + { 96.57, 96.95, 91.53, ​ 280.69, 156.79, 436.58, 0.0864 },
 + { 160.44, 162.49, 159.06, ​ 355.98, 115.89, 591.24, 0.0636 },
 + { 74.98, 63.23, 46.33, ​ 414.84, 245.95, 361.27, 0.0747 },
 + { 121.83, 60.88, 18.31, ​ 2502.24, 1383.53, 237.18, 0.0365 },
 + { 202.18, 154.88, 91.04, ​ 957.42, 1766.94, 1582.52, 0.0349 },
 + { 193.06, 201.93, 206.55, ​ 562.88, 190.23, 447.28, 0.0649 },
 + { 51.88, 57.14, 61.55, ​ 344.11, 191.77, 433.40, 0.0656 },
 + { 30.88, 26.84, 25.32, ​ 222.07, 118.65, 182.41, 0.1189 },
 + { 44.97, 85.96, 131.95, ​ 651.32, 840.52, 963.67, 0.0362 },
 + { 236.02, 236.27, 230.70, ​ 225.03, 117.29, 331.95, 0.0849 },
 + { 207.86, 191.20, 164.12, ​ 494.04, 237.69, 533.52, 0.0368 },
 + { 99.83, 148.11, 188.17, ​ 955.88, 654.95, 916.70, 0.0389 },
 + { 135.06, 131.92, 123.10, ​ 350.35, 130.30, 388.43, 0.0943 },
 + { 135.96, 103.89, 66.88, ​ 806.44, 642.20, 350.36, 0.0477 }
 +};
 +
 +double skin_value(Color R, Color G, Color B) {
 +  double r = 0;
 +  for(unsigned i=0; i<nG; i++) {
 +    double t;
 +    t = pow(double(R)-skin[i][0],​2)/​skin[i][3] + pow(double(G)-skin[i][1],​2)/​skin[i][4] + pow(double(B)-skin[i][2],​2)/​skin[i][5];​
 +    t = skin[i][6]*exp(-t/​2) / (pow(2*M_PI,​1.5) * sqrt(skin[i][3]*skin[i][4]*skin[i][5]));​
 +    r += t;
 +  }
 +  return r;
 +}
 +
 +double noskin_value(Color R, Color G, Color B) {
 +  double r = 0;
 +  for(unsigned i=0; i<nG; i++) {
 +    double t;
 +    t = pow(double(R)-noskin[i][0],​2)/​noskin[i][3] + pow(double(G)-noskin[i][1],​2)/​noskin[i][4] + pow(double(B)-noskin[i][2],​2)/​noskin[i][5];​
 +    t = noskin[i][6]*exp(-t/​2) / (pow(2*M_PI,​1.5) * sqrt(noskin[i][3]*noskin[i][4]*noskin[i][5]));​
 +    r += t;
 +  }
 +  return r;
 +}
 +</​code>​
 +
 +==== Trabalho 5 (Teste de primalidade) ====
 +
 +Entrega: 26/11/2014
 +
 +=== Objetivos ===
 +  * Implementar o teste de primalidade de Miller & Rabin
 +  * Analisar a complexidade do algoritmo em função do tamanho da entrada (log_2(n)) experimentalmente.
 +  * Analisar a probabilidade de responder erradamente "​sim"​ experimentalmente.
 +
 +=== Casos de teste ===
 +  * Números inteiros positivos aleatórios.
 +
 +=== Convenções ===
 +  * As implementações do algoritmo devem ler um número decimal com até 1000 dígitos da entrada padrão e imprimir "​s"​ na saída padrão caso o número é considerado primo e "​n"​ caso contrário.
 +
 +=== Dicas ===
 +  * Usa a biblioteca {{http://​gmplib.org|GNU MP}} para representar números grandes. Ela tem interfaces para {{http://​en.wikipedia.org/​wiki/​GNU_Multiple_Precision_Arithmetic_Library#​Language_bindings|diversas linguagens}} de programação e é simples de usar. Um exemplo em C++:
 +  <code c++>
 +#include <​iostream>​
 +using namespace std;
 +
 +#include <​gmpxx.h>​
 +
 +int main(int argc, char *argv[]) {
 +  mpz_class a;
 +  cin >> a;
 +  cout << "O quadrado de " << a << " é " << a*a << endl;
 +}
 +</​code>​
  
inf05016/2014-2-trabalhos.1407341094.txt.gz · Esta página foi modificada pela última vez em: 2014/08/06 13:04 por marcus