MAC0328 Algoritmos em Grafos

Quarto Exerc�cio-Programa. Passeios M�nimos

"Highways, telephone lines, electric power systems, computer chips,
water delivery systems, and rail lines: these physical networks, and
many others, are familiar to all of us. In each of these problem settings,
we often wish to send some good(s) (vehicles, messages, electricity, or
water) from one point to another, typically as efficiently as possible --
that is, along a shortest route or via some minimum cost flow pattern.''

- Ahuja, Magnanti, Orlin, and Reddy


Objetivos

  1. Implementar um algoritmo para o Problema dos Passeios M�nimos: Algoritmo de Bellman-Ford-Moore.
  2. Uso de busca em largura para obten��o de passeios. Veja tamb�m busca em largura vers�o 2001.

Descri��o

Introdu��o

Este exerc�cio-programa consiste na implementa��o do algoritmo de Bellman-Ford-Moore que recebe um grafo g com comprimentos nos arcos e um v�rtice r e devolve um ciclo negativo acess�vel a partir de r ou um passeio de comprimento m�nimo de r a v, para cada v�rtice v do grafo. O comprimento len(a) de cada arco a de g � um n�mero inteiro (possivelmente negativo). Se

P=<r=v0,a1,v1,a2,v3,...,vk-1,ak,vk=v>
� um passeio de um v�rtice r a um v�rtice v ent�o seu comprimento len(P)
len(a1) + len(a2) + ... + len(ak).
Assim, o comprimento de um passeio � a soma dos comprimentos do arcos no passeio; levando-se em conta o n�mero de vezes que cada arco ocorre no passeio. Um passeio P � dito (de comprimento) m�nimo se len(P) <= len(P') para todo passeio P' com a mesma ponta inicial e a mesma ponta final de P. A dist�ncia de um v�rtice r a um v�rtice v � o menor comprimento de um caminho de r a v.

O seu programa C (documento CWEB) deve chamar-se bellman.c (bellman.w, respectivamente). O programa deve utilizar a biblioteca do SGB para representa��o e recupera��o um grafo, como descrito a seguir.

Nota. A descri��o do algoritmo de Bellman-Ford-Moore que est� abaixo foi extra�da do livro:

R.E. Tarjan, Data Structures and Network Algorithms, CBMS-NSF Regional Conference Series in Applied Mathematics, Philadelphia, Pennysylvania, 1983.


Algoritmo de Bellman-Ford-Moore

Seja g um grafo com comprimentos nos arcos e r um v�rtice de g. Denotaremos por n e m o n�mero de v�rtices e de arcos de g.

Passeios e caminhos m�nimos

Nem sempre existe um passeio m�nimo de um v�rtice r a um v�rtice v.

Teorema 0. Sejam r e v v�rtices de um grafo com comprimentos nos arcos. Suponha que v � acess�vel a partir de r. Vale uma, e apenas uma, das seguintes afirma��o:

  1. existe um passeio m�nimo de r a v; ou
  2. existe um passeio de r a v que percorre um ciclo (de comprimento) negativo.

Demonstra��o. Exerc�cio.

� evidente que se v � acess�vel a partir de r, ent�o existe um caminho m�nimo de r a s. Entretanto, encontrar caminhos m�nimos � um problema computacionamente dif�cil (a menos, � claro, que n�o tenhamos pressa em encontrar o caminho). Encontrar um caminho m�nimo de r a v � t�o dif�cil quanto encontrar um caminho hamiltoniano de r a v (um problema dif�cil pra cachorro).

Felizmente (ou curiosamente) existem algoritmos eficientes para encontrar-se passeios m�nimos quando estes existem. Mais ainda, os passeios (m�nimos) encontrados pelos algoritmos s�o caminhos. Uma maneira compacta de representar passeios/caminhos m�nimos de um dado v�rtice r a todos os demais v�rtices de um grafo � atrav�s de uma certa �rvore com raiz r.

�rvore de caminhos m�nimos

Um �rvore (ou arboresc�ncia) com raiz r � dita uma �rvore de caminhos m�nimos se todo v�rtice acess�vel a partir de r est� na �rvore e para cada v�rtice v na �rvore o caminho de r a v na �rvore � um passeio m�nimo no grafo.

Teorema 1. Seja g um grafo com comprimentos nos arcos e r um de seus v�rtices. Vale uma, e apenas uma, das seguintes afirma��o:

  1. g possui uma �rvore de caminhos m�nimos com raiz r; ou
  2. g possui um ciclo negativo acess�vel a partir de r.

Demonstra��o. Exerc�cio. (Este teorema � uma das conseq��ncias da corre��o do algoritmo de Bellman-Ford-Moore.)

Se t � uma �rvore (ou arboresc�ncia) de g com raiz r e v � um v�rtice de g, ent�o definimos dist[v] como sendo o comprimento do �nico caminho de r a v na �rvore.  Note que dist[v] n�o � a dist�ncia r a v no grafo, mas sim na �rvore; por esta raz�o dist[v] � muitas vezes chamdo de dist�ncia tentativa (ou candidato a dist�ncia) de r a v no grafo. Para os v�rtices que n�o est�o em t definimos dist[v] como sendo INFINITO, onde INFINITO � um n�mero suficientemente grande. Se n � o n�mero de v�rtices do grafo e L � o valor absoluto do maior comprimento de um arco ent�o, para os nossos prop�sitos, podemos considerar que INFINITO = n � L + 1. Note que para cada arco uv na �rvore vale que

dist[u] + len(uv) = dist[v].

O m�todo descrito a seguir baseia-se no teorema abaixo.

Teorema 2. Uma �rvore com raiz r � de caminhos m�nimos se e somente se

dist[u] == INFINITO   ou    dist[v] <= dist[u] + len(uv,)   para cada arco uv de g,
onde dist[w] � o comprimento do caminho de r a w na �rvore.

Demonstra��o. Exerc�cio. :-)

O teorema 2 pode ser usado na implementa��o de um trecho de c�digo que em tempo linear verifica se uma suposta �rvore de caminhos m�nimos � de fato uma �rvore de caminhos m�nimo Esta v�rifica��o ser� usada na implementa��o do algoritmo de Bellman-Ford-Moore, veja a se��o ``comportamento do se programa''.

EXERC�CIO :  Escreva uma fun��o

          int distancias_ok (Graph *g, Vertex *r){...}
que recebe um grafo  g  com comprimentos nos arcos (possivelmente negativos) e um v�rtice r e devolve 1 se para cada v�rtice v o valor v->dist � dist�ncia de r a v, em caso contr�rio a fun��o devolve 0. O consumo de tempo de sua fun��o deve ser linear.

Labeling method

O teorema 2 sugeri o seguinte m�todo iterativa, o chamado labeling method, para tentar construir uma �rvore de caminhos m�nimos com raiz r.

No in�cio de cada itera��o tem-se uma �rvore t com raiz r e o comprimento dist[v] do caminho de r a v na �rvore, para cada v�rtice v do grafo. Para representar a �rvore t tem-se uma fun��o predecessor que para cada v�rtice v fornce o v�rtice pred[v] predecessor (ou pai) de v na �rvore.
No in�cio da primeira itera��o pred[v] = NULL para cada v�rtice v, dist[r] = 0 e dist[v] = INFINITO para os demais v�rtices.
Itere o seguinte passo at� que dist[u] + len(u,v) >= dist[v] para cada arco uv do grafo:

LABELING STEP (L.R. Ford). Selecione um arco uv  tal que  dist[v] > dist[u] + len(uv). Fa�a

dist[v] = dist[u] + len(u,v)   e   pred[v] = u.

O labeling method n�o p�ra caso o grafo contenha um ciclo negativo. Ademais, mesmo que o grafo n�o contenha ciclos negativos e o m�todo pare, ele pode demorar muito. Nosso primeiro refinamento ser� evitar que arcos sejam examinados desnecessariamente.

EXERC�CIO :  Mostre um grafo com comprimentos arbitr�rios e sem ciclos negativos em que o LABELING STEP consome tempo exponecial.

Labeling and scanning method

O labeling and scanning method mant�m uma parti��o dos v�rtices em tr�s estados: N�O-VISTO, VISITADO e EXAMINADO. Os v�rtices no estado VISITADO ou EXAMINADO s�o exatamente aqueles que t�m `dist�ncia tentativa' finita. Inicialmente rVISITADO e os demais v�rtices s�o N�OVISTOS. O m�todo consiste em iterar o seguinte passo at� que n�o hajam v�rtices com estado VISITADO.

SCANNING STEP. Selecione um v�rtice VISITADO u e examine-o, mudando o seu estado para EXAMINADO, atrav�s da aplica��o do labeling step a cada arco uv tal que dist[u] + len(u,v) < dist[v] e convertendo o estado de v para VISITADO (n�o importa se o estado de v era N�O-VISTO ou EXAMINADO).

O labeling and scanning method, a exemplo do labeling method, � ineficiente e n�o p�ra caso o grafo contenha um ciclo negativo acess�vel a partir de r. Entretanto, podemos transformar este m�todo em um algoritmo eficiente atrav�s de uma escolha apropriado da ordem em que os v�rtices no estado VISITADO s�o examinados, como descrito logo a seguir.

Ordem da busca em largura

E.F. Moore e, independentemente, R.E. Bellman propuseram que os v�rtices com estado VISITADO fossem examinados de acordo com uma ordem de busca em largura (breadth-first order): entre os v�rtices com estado VISITADO examine aquele que est� nesse estado a mais tempo. Para implementar a busca em largura representamos o conjunto de v�rtices no estado VISITADO atrav�s de uma fila. Nesta implementa��o surge a quest�o do que fazer com um v�rtice no estado VISITADO que � visitado novamente. Um interpreta��o estrita de busca em largura requer que n�s movamos um tal v�rtice no estado VISITADO para o fim da fila. Entretanto, aplicaremos uma interpreta��o mais livre, deixaremos o v�rtice no estado VISITADO na sua posi��o corrente na fila. A descri��o abaixo implementa esta vers�o do labeling and scanning method usando busca em largura. Note que o m�todo, como descrito, ainda n�o p�ra se o grafo cont�m ciclos negativos.










10 
11 
12 
13 
14 
15 
16 
17 
BELLMAN-FORD-MOORE (Grafo g, V�rtice r)
  para cada v�rtice v de g fa�a
      estado[v] := N�O-VISTO
      dist[v] := INFINITO
      pred[v] := NULL
  estado[r] := VISITADO
  dist[r] := 0
  Q := INICIALIZA-FILA(r)
  enquanto Q n�o est� vazia fa�a
      u := PRIMEIRO-DA-FILA(Q)
      para cada uv em Adj[u] fa�a
          se dist[u] + len(u,v) < dist[v] ent�o
            estado[v] := VISITADO
            dist[v] := dist[u]+len(u,v)
            pred[v] := u
            se v n�o est� em Q ent�o
              INSIRA-NA-FILA(Q,v)
      estado[u] := EXAMINADO
  devolva dist e pred

Ao longo do algoritmo, Q � uma fila de v�rtices; essa fila � o segredo do funcionamento do algoritmo. O comando INICIALIZA-FILA(r) cria uma fila com um s� elemento, o v�rtice r. O comando PRIMEIRO-DA-FILA(Q) devolve e remove o primeiro elemento da fila Q. O comando INSIRA-NA-FILA(Q,v) insere v no fim da fila Q.

Para analisar o desempenho deste m�todo divide-se a sua execu��o em passos. O passo zero consiste do exame do v�rtice r. Para j > 0, o passo j consiste do exame de todos os v�rtices na fila ao final do passo j - 1. Cada passo pode ser executado em tempo O(n+m) pois durante cada passo cada v�rtice e cada arco � examinado no m�ximo uma vez. (Hmmm, esse O(n+m) pode ser trocado por O(m). Por qu�?) O teorema a seguir fornece um limitante superior para o n�mero total de passos.

Teorema 3. Se g � um grafo com n v�rtices,m arcos e sem ciclos negativos acess�veis a partir de r, ent�o o m�todo de BELLMAN-FORD-MOORE gasta tempo O(n+nm) e n�o mais do que n-1 passos s�o realizados.

Demonstra��o. Pode-se mostrar por indu��o em k que se existe um passeio m�nimo de r a um v�rtice v usando k arcos, ent�o no in�cio do passo k a dist�ncia tentativa dist[v] � menor ou igual ao comprimento deste passeio m�nimo.

Ciclos negativos

Para transforma o m�todo de Bellman-Ford-Moore acima em um algoritmo deve-se fazer com que ele pare mesmo na presen�a de ciclos negativos. Uma maneira f�cil de fazer isto � contar o n�mero de passos executados. Inclua duas vari�veis ao m�todo, um inteiro passo e uma v�riavel �ltimo indicando o �ltimo v�rtice que foi examinado durante o presente passo do m�todo. Inicialmente passo = 0 e �ltimo = r. Depois que o v�rtice �ltimo � examinado incrementa-se de 1 a vari�vel passo e �ltimo passa a ser o �ltimo v�rtice da fila Q. Se passo recebe o valor n com a fila Q n�o vazia, o (agora) algoritmo deve parar e anunciar a presen�a de um ciclo negativo no grafo. Com este contador de passos o algoritmo gasta tempo O(n + nm) n�o importando se o grafo tem ou n�o um ciclo negativo. Usando o lema a seguir pode-se localizar um ciclo negativo, caso um tal ciclo exista. Se v � um v�rtice, ent�o

pred1[v] = pred[v]
pred2[v] = pred[pred[v]]
pred3[v] = pred[pred[pred[v]]]
[...]
e assim por diante.

Lema 4. Se a fila Q n�o est� vazia no final do passo n-1 ent�o predk[v] = v para algum v�rtice v e inteiro k e o correspondente ciclo em g � negativo.

Demonstra��o. Suponha que o algoritmo � executado at� que um v�rtice w seja examinado no passo n. Defina passo[v] de um v�rtice v como sendo o m�ximo j tal que v � examinado durante o passo j. Se passo[v] � definido e positivo ent�o pred[v] e passo[pred[v]] s�o definidos e passo[pred[v]] >= passo[v] - 1. Temos que passo[w]=n. Seguindo os apontadores pred a partir de w nos devemos, em algum momento, repetir algum v�rtice, pois existem somente n v�rtices e o passo de cada v�rtice decresce de no m�ximo um em cada passo.

M�todo de Bellman-Ford-Moore e programa��o din�mica

Uma descri��o alternativa do m�todo de Bellman-Ford-Moore, mais pr�xima de programa��o din�mica, � a que passamos a apresentar.

Defina para cada v�rtice v o valor dk(v) como sendo o menor comprimento de um passeio de r a v que possui no m�ximo k arcos, fa�a dk(v) = INFINITO se n�o existe um tal passeio.

Claramente, se n�o existe um ciclo negativo acess�vel a partir de r, a dist�ncia de r a v � igual a dn(v) (na verdade, dn-1(v)).

Algoritmicamente, a fun��o d0 � f�cil de ser computada: d0(r) = 0 e d0(v) = INFINITO se v � um v�rtice distinto de r. Em seguida, d1, d2, d3,... podem ser computadas sucessivamente atrav�s da seguinte regra:

dk+1(v) = min{dk(v), min(dk(u)+len(uv): uv arco)}
para cada v�rtice v.

Este m�todo fornece a dist�ncia de r a v, para cada v�rtice v. Como vimos anteriormente n�o � dif�cil adaptar o m�doto para construir uma �rvore de caminhos m�nimo com raiz r; se o grafo n�o possui ciclo negativo � claro.

Teorema 5. Dados um grafo com comprimentos nos arcos e um v�rtice r tais que todo ciclo acess�vel a partir de r tem comprimento n�o-negativo, uma �rvore de caminhos m�nimos com raiz em r pode ser encontrada em tempo O(n2+nm).

Demonstra��o. Existem no m�ximo n itera��es e cada uma consome tempo O(n+m).

Um ciclo negativo pode ser determinado de maneira semelhante.

Teorema 6. Dados um grafo com comprimentos nos arcos e um v�rtice r, um ciclo negativo acess�vel a partir de r pode ser encontrado em tempo O(n2+nm).

Demonstra��o. Se dn != dn-1, ent�o dn(v) < dn-1(v) para algum v�rtice v. Logo, o algoritmo encontra um passei P de r a v de comprimento dn(v), que atravessa n arcos. Como P atravessa n arcos, ent�o P cont�m um ciclo C. Removendo C de P obt�m-se um passeio P' de r a v com menos do que n arcos. Assim,

len(P') >= dn-1(v) > dn(v) = len(P) = len(P') + len(C)
e portanto len(C) < 0.
Se dn = dn-1, ent�o n�o existe ciclo negativo acess�vel a partir de r.

Tendo em vista o algoritmo de programa��o din�mica dsecrito acima pode-se facilmente implementar uma fun��o

void bellman-ford-moore (Graph *g, Vertex *r) {...}
que recebe um grafo g com comprimentos arbitr�rios nos arcos e um v�rtice r e se o grafo n�o tem um ciclo negativo acess�vel a partir de r, ent�o devolve um caminho de comprimento m�nimo de r a v para cada v�rtice v do grafo. Eis a fun��o
void
bellman-ford-moore (Graph *g, Vertex *r)
{
  Vertex *u0 = g->vertices;
  Vertex *un = g->vertices + g->n;
  long passo;

  for (u = u0; u < un; u++) 
    {
      u->dist = infinito;
      u->pred = NULL;
    }

  r->dist = 0;
  for (passo = 0; passo < n; passo++)
    {
      for (u = u0; u < un; u++)
        {
          if (u->dist != infinito) 
           {
             Arc *a;
            
             for (a = u->arcs; a; a = a->next)
               {
                 Vertex *v = a=>tip;
                 long d = u->dist + a->len;

                 if (v->dist > d) 
                   {
                     v->dist = d;
                     v->pred = u;
                   }
               }
           }
        }
    }
}

Este trecho de c�digo exibe a simplicidade do m�todo. O consumo de tempo da fun��o bellman-ford-mooreO(n2 + nm). Do ponto de vista de consumo de tempo assint�tico de pior caso, esta fun��o � t�o eficiente quanto a que ser� implementada neste exerc�cio-programa. Entretanto, a implementa��o sugerida para este exerc�cio-programa � mais eficiente na pr�tica.

EXERC�CIO (An�lise experimental) :  Compare o consumo de tempo do seu exerc�cio-programa com o consumo de tempo da fun��o acima.

Comportamento do seu programa

Neste exerc�cio-programa voc� implementar� o Algoritmo de Bellman-Ford-Moore para encontrar passeios m�nimos em grafos com arcos de comprimentos arbitr�rios (possivelmente negativos). Voc� pode escrever o programa em C cru ou em CWEB.  Documente corretamente todas as fun��es do programa.

O programa deve receber como entrada um grafo, um v�rtices origem e um v�rtice destino e deve fornecer como sa�da um passeio m�nimo do v�rtice origem ao v�rtice destino.

O nome do seu programa dever� ser bellman e poder� ser chamado das seguintes formas (voc� pode implementar mais funcionalidades de desejar):

bellman

Como sa�da o programa dever� imprimir uma mensagem explicando o seu funcionamento.

bellman -n "nome do v�rtice origem" "nome do v�rtice destino" nome_do_grafo[.gb]

O seu programa deve determinar o passeio m�nimo no grafo nome_do_grafo do v�rtice de nome "nome do v�rtice origem" ao v�rtice de nome "nome do v�rtice destino". As aspas s�o importantes para a determina��o correta dos nomes dos v�rtices.

bellman n�mero_vertice_origem n�mero_vertice_destino nome_do_grafo[.gb]

O seu programa deve determinar o passeio m�nimo no grafo nome_do_grafo do v�rtice de n�mero n�mero_vertice_origem ao v�rtice de n�mero n�mero_vertice_destino. Vamos convencionar que o primeiro v�rtice do grafo tem n�mero 0.

bellman -t ...

Os "..." representam uma das duas op��es anteriores. Se a op��o -t (todos) � usada, o seu programa deve determinar um passeio m�nimo no grafo nome_do_grafo.gb do v�rtice de nome v�rtice origem a cada um dos demais v�rtices. Neste caso, o nome ou n�mero de v�rtice destino s�o superfluos.

bellman -v ...

Os "..." representam uma das tr�s op��es anteriores. Quando o usu�rio usar a op��o -v (verbose) forne�a tamb�m os comprimentos dos passeios que foram encontrados antes do passeio m�nimo desejado. Se voc� desejar forne�a, al�m dos comprimentos dos passeios m�nimos e os v�rtices de suas extremidades, as seq��ncias completas de v�rtices que definem o passeio.
[Creio que isto deve ajudar na fase de implemeta��o.]

O seu programa deve prever pelo menos os seguintes casos, informando o fato ao usu�rio com uma mensagem conveniente:

  1. o programa � chamado com par�metros incorretos;
  2. o grafo nome_do_grafo.gb n�o � encontrado;
  3. algum dos v�rtices n�o � encontrado; e
  4. n�o existe passeio do v�rtice origem ao v�rtice destino;
  5. Se o grafo cont�m um ciclo negativo acess�vel a partir do v�rtice origem, ent�o o seu programa dever� exibir um ciclo negativo.

N�o deixe de incluir algumas fun��es de auto-teste em seu programa: Se o usu�rio digitar a op��o "-teste", essas fun��es far�o testes em v�rios pontos do programa. Por exemplo, verificar�o se um suposto caminho � de fato um caminho, se uma suposta �rvore de caminhos m�nimos � de fato uma �rvore de caminhos m�nimo, etc Se a op��o "-teste" estiver ativa, � uma boa id�ia exibir a seq��ncia de v�rtices sendo examinados.

Sugest�es s�o bem-vindas!

Sa�da do seu programa

A sa�da do seu programa deve ser enviada para a sa�da padr�o (stdout).

Os comprimentos dos passeios m�nimos encontrados devem ser fornecido, bem como o passeio do v�rtice origem ao(s) v�rtice(s) destino(s). Se o programa � chamado com os nomes dos v�rtices, os passeios m�nimos fornecidos na sa�da devem listar os nomes dos v�rtices. Caso o programa seja chamado usando os n�meros dos v�rtices, os passeios fornecidos devem listar os n�meros dos v�rtices.


Detalhes de implementa��o

Voc� pode implementar o algoritmo de Bellman-Ford-Moore como uma fun��o em seu programa, de forma a permitir que, no futuro, a mesma fun��o possa ser usada inalterada por outros programas que voc� escrever, nesta ou em outras disciplinas.

O algoritmo precisa de uma estrutura de dados auxiliar que permita as opera��es INICIALIZA-FILA, PRIMEIRO-DA-FILA, INSIRA-NA-FILA, e REMOVA-DA-FILA. A fila pode ser implementada como uma lista duplamente ligada com cabe�a de v�rtices (estruturas do tipo Vertex). Como fizemos para o algoritmo de Dijkstra.

Agora, vamos imaginar que um dia voc� queira usar, ou testar, uma outra estrutura de dados para representar est� fila, talvez mais r�pida. Levando isso em considera��o, o uso da fila em seu programa deve ser de tal forma modularizada que permita, sem necessidade de mudan�as na fun��o principal do bellman, que outra estrutura de dados substitua em seu programa as rotinas de fila que voc� escrever.

Se voc� est� em busca de inspira��o, ent�o d� uma olhada no modulo GB_DIJK (gb_dijk.w) do SGB para ver uma implementa��o do Algoritmo Dijkstra. O m�dulo MILES_SPAN (miles_span.w) cont�m uma implementa��o de uma fila atrav�s de um heap.

Grafo de cidades brasileiras

O professor Jos� Augusto fez programas para criar grafos (.gb) de cidades brasileiras. Veja os dados, grafos e os programas em http://www.ime.usp.br/~coelho/grafos/sgb/cidades/. Voc� pode usar este grafo de cidades brasileiras para brincar com o seu programa.

M�dulo GB_MILES

O m�dulo GB_MILES (gb_miles.w) do SGB cont�m a subrotina miles que voc� pode usar para testar e brincar com o seu programa bellman.

Copiado do arquivo gb_miles.w:

The subroutine call

miles(n,north_weight,west_weight,pop_weight,max_distance,max_degree,seed)

constructs a graph based on the information in miles.dat. Each vertex of the graph corresponds to one of the 128 cities whose name is alphabetically greater than or equal to `Ravenna, Ohio' in the 1949 edition of Rand McNally & Company's Standard Highway Mileage Guide. Edges between vertices are assigned lengths representing distances between cities, in miles. In most cases these mileages come from the Rand McNally Guide, but several dozen entries needed to be changed drastically because they were obviously too large or too small; in such cases an educated guess was made. Furthermore, about 5% of the entries were adjusted slightly in order to ensure that all distances satisfy the ``triangle inequality'': The graph generated by miles has the property that the distance from u to v plus the distance from v to w always exceeds or equals the distance from u to w.

The constructed graph will be ``complete''---that is, it will have edges between every pair of vertices---unless special values are given to the parameters max_distance or max_degree. If max_distance!=0, edges with more than max_distance miles will not appear; if max_degree!=0, each vertex will be limited to at most max_degree of its shortest edges.

Um exemplo de uso da fun��o miles pode ser encontrado no m�dulo MILES_SPAN (miles_span.w), como mostrado abaixo.

#include "gb_miles.h" /* the |miles| routine */
[...]
main(argc,argv)
  int argc; /* the number of command-line arguments */
  char *argv[]; /* an array of strings containing those arguments */
{@+unsigned long n=100; /* the desired number of vertices */
  unsigned long n_weight=0; /* the |north_weight| parameter */
  unsigned long w_weight=0; /* the |west_weight| parameter */
  unsigned long p_weight=0; /* the |pop_weight| parameter */
  unsigned long d=10; /* the |max_degree| parameter */
  long s=0; /* the random number seed */
  unsigned long r=1; /* the number of repetitions */
  char *file_name=NULL; /* external graph to be restored */
  @;
  while (r--) {
    if (file_name) g=restore_graph(file_name);
    else g=miles(n,n_weight,w_weight,p_weight,0L,d,s);
    if (g==NULL || g->n<=1) {
      fprintf(stderr,"Sorry, can't create the graph! (error code %ld)\n",
               panic_code); /* panic_code is set nonzero if graph
                             * generator panics. 
                             * panic_code indica o problema que ocorreu,
                             * veja gb_graph.w
                             */
      return -1; /* error code 0 means the graph is too small */
    }

M�dulo GB_RAND

Copiado do arquivo m�dulo GB_RAND (gb_rand.w):

This GraphBase module provides two external subroutines called random_graph and random_bigraph, which generate graphs in which the arcs or edges have been selected ``at random.'' A third subroutine, random_lengths, randomizes the lengths of the arcs of a given graph. The performance of algorithms on such graphs can fruitfully be compared to their performance on the nonrandom graphs generated by other GraphBase routines.

[...]

The procedure

random_graph(n,m,multi,self,directed,dist_from,dist_to, min_len,max_len,seed)

is designed to produce a pseudo-random graph with n vertices and m arcs or edges, using pseudo-random numbers that depend on seed in a system-independent fashion. The remaining parameters specify a variety of options:
multi!=0 permits duplicate arcs;
self!=0 permits self-loops (arcs from a vertex to itself);
directed!=0 makes the graph directed; otherwise each arc becomes an undirected edge;
dist_from and dist_to specify probability distributions on the arcs;
min_len and max_len bound the arc lengths, which will be uniformly distributed between these limits.

If dist_from or dist_to are NULL, the probability distribution is uniform over vertices; otherwise the dist parameter points to an array of n nonnegative integers that sum to 230, specifying the respective probabilities (times 230) that each given vertex will appear as the source or destination of the random arcs.

[...]

Sugest�o

Brinque com o seu programa, brinque muito. Aplique-o ao grafo de cidades brasileiras e a v�rios grafos do Stanford GraphBase (use as fun��es miles e random_graph. Durante a fase de testes, use grafos pequenos. Fa�a um desenho do grafo num peda�o de papel para conferir a resposta do seu programa.

Uso de WEB

Gostaria de destacar que o uso do WEB, segundo o seu criador D. Knuth, tem as seguintes finalidades de

Como conseq��ncia, Knuth comenta que fica mais divertido escrever programas.

Mudando de assunto, um coment�rio sobre coment�rios: ``Antes de cada fun��o [e bloco] diga o que a fun��o [e bloco] faz. Procure responder as perguntas que um usu�rio faria: que dados essa fun��o recebe? que suposi��es faz sobre esses dados? que resultados devolve? N�o perca tempo tentando dizer como a fun��o faz o que ela faz.''(Paulo Feofiloff) Se o tamanho de seus blocos � razoavelmente pequeno, como deve ser, o conselho � extremamente �til.

Observa��o. C�piei o coment�rio acima da p�gina de grafos do prof. Jos� Augusto


Entrega e Prazos

  1. Este exerc�cio-programa vale 20 pontos.
  2. Como sempre, somente entregue seu programa se o mesmo n�o apresentar erros de compila��o. O processo de compila��o aqui deve ser entendido como todo o processo cweave, latex, ctangle (se voc� fez em CWEB) e gcc.
  3. Junto com o seu programa voc� deve entregar um Makefile de tal forma que
    meu_prompt> make bellman.tex
    gere o documento bellman.tex correspondente ao seu EP4,
    meu_prompt> make bellman.dvi
    produza o Make.dvi correspondente ao seu EP4,
    meu_prompt> make bellman.c
    crie o arquivo bellman.c correspondente ao seu EP4, e
    meu_prompt> make bellman
    produza o execut�vel de nome bellman correspondente ao seu EP4.
  4. O Panda n�o costuma aceitar a entrega de v�rios arquivos. Por isto, voc� deve criar um arquivo ep4.tar.gz com todo o seu trabalho. Espera-se que
    meu_prompt>tar -xvf ep4.tar
    crie um diret�rio que tenha o seu login na rede Linux como nome. Neste diret�rio devem estar todos os arquivos do seu EP3, inclusive o Makefile que voc� usou. Se voc� achar necess�rios coloque junto um arquivo 00-leia-me, onde voc� descreve algo que achar necess�rio: como limita��es e bugs no seu programa.
  5. O seu EP4s deve ser dep�sitado no panda at� o 24:00 do dia 12 MAI 2003.

[ P�gina principal de algoritmos em grafos. | Exerc�cios-programas]
Last modified: Sun May 4 22:19:21 EST 2003