Esta página mostra as diferenças entre as duas revisões da página.
| Ambos os lados da revisão anterior Revisão anterior Próxima revisão | Revisão anterior | ||
|
inf05016:2014-2-trabalhos [2014/08/06 13:09] marcus |
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 9: | Linha 9: | ||
| * 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. | * Avaliar o escalonamento do algoritmo Dijkstra. | ||
| - | * | + | |
| === Casos de teste === | === Casos de teste === | ||
| - | * O 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 98: | 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> | ||