Sei sulla pagina 1di 43

Faculdade Anhanguera de Jacare - SP

ATPS INTELIGNCIA ARTIFICIAL


Engenharia de Controle e Automao

Jacare SP
Setembro/2015

Faculdade Anhanguera de Jacare - SP

ATPS INTELIGENCIA ARTIFICIAL


Engenharia de Controle e Automao

Anderson Luiz da Silva Candido

RA: 2504098261

Carlos Alexandre de Azevedo

RA: 2505000265

Felipe Bondio

RA: 2505000269

Leandro Mendes Machado

RA: 2524419934

Mauricio Tadeu Monteiro de Campos

RA: 2505000275

Rudson Francisco Morais

RA: 4423853085

Engenharia de Controle e Automao

10 srie
Professor: Eduardo

Jacare - SP
Setembro/2015

Sumrio
1. EVOLUO DA INTELIGNCIA ARTIFICIAL..................................................4
1.1Clssica (1956-1970)...................................................................................5
1.2 Romntica (1970-1980)...............................................................................5
1.3 Moderna (1980-1990).....................................................................................5
1.4 Clssica.......................................................................................................6
1.5 Romntica...................................................................................................7
1.6 Moderna......................................................................................................8
2.0 GRAFOS EM LINGUAGEM DE PROGRAMAO C....................................9
2.1 Registro.....................................................................................................10
2.2 Main...........................................................................................................11
2.3 Menu..........................................................................................................12
2.4 Insero das Arestas.................................................................................13
2.5 Impresso da lista de adjacentes..............................................................18
2.6 Busca em largura......................................................................................20
2.7 Busca em profundidade............................................................................23
2.8 Cdigo completo Grafo.............................................................................25
3. RESOLUO DE PROBLEMAS POR MEIO DE BUSCA.............................34
3.1 Agentes de resoluo de problemas.........................................................34
3.2 Busca.........................................................................................................34
3.3 Formulao de problemas.........................................................................35
3.4 Espao de estados....................................................................................36
3.5 Selecionando um espao de estados.......................................................36
3.6 Problemas do mundo real.........................................................................39
3.7 Busca de solues....................................................................................40
3.8 Descrio informal do algoritmo geral de busca em rvore.....................41
3.9 Estados vs. Ns........................................................................................42
4.0 Algoritmo geral de busca em rvore.........................................................43
4.1 Estratgias de busca.................................................................................43

1. EVOLUO DA INTELIGNCIA ARTIFICIAL

1960 Pr - IA

Lisp Sistemas de Produo (evoluo de sistemas genricos).

1960 - 1965 Perodo do entusiasmo Macsyma, Dendral;

1965 - 1970 Perodo das Trevas Conscientizao das limitaes;

1970 - 1975 Perodo da renascena;

Hearsy, Mycin (ajudava a diagnosticar doenas no sangue, tinha 450 regras


e fazia anlise do sangue), Prospector (fazia prospeco geolgica), Prolog;

1975 - 1980 Perodo da associao reas de aplicao;

Perodo do empreendimento;

Popularizao de SE Ferramentas e Ambientes;

As correntes de pensamento que se cristalizaram em torno da IA j estavam


em gestao desde os anos 30. No entanto, oficialmente, a IA nasceu em 1956 com
uma conferncia de vero em Dartmouth College, NH, USA. Na proposta dessa
conferncia, escrita por John McCarthy (Dartmouth), Marvin Minsky (Hardward),
Nathaniel Rochester (IBM) e Claude Shannon (Bell Laboratories) e submetida
fundao Rockfeller, consta a inteno dos autores de realizar um estudo durante
dois meses, por dez homens, sobre o tpico inteligncia artificial. Ao que tudo indica,
esta parece ser a primeira meno oficial expresso Inteligncia Artificial. Desde
seus primrdios, a IA gerou polmica, a comear pelo seu prprio nome, considerado
presunoso por alguns, at a definio de seus objetivos e metodologias. O
desconhecimento dos princpios que fundamentam a inteligncia, por um lado, e dos
limites prticos da capacidade de processamento dos computadores, por outro, levou
periodicamente a promessas exageradas e s correspondentes decepes.

Dada impossibilidade de uma definio formal precisa para IA, visto que
para tanto seria necessrio definir, primeiramente, a prpria inteligncia, foram
propostas algumas definies operacionais: uma mquina inteligente se ela capaz
de solucionar uma classe de problemas que requerem inteligncia para serem
solucionados por seres humanos; inteligncia Artificial a parte da cincia da
computao que compreende o projeto de sistemas computacionais que exibam
caractersticas associadas, quando presentes no comportamento humano,
inteligncia; ou ainda Inteligncia Artificial o estudo das faculdades mentais atravs
do uso de modelos computacionais. Outros se recusam a propor uma definio para o
termo e preferem estabelecer os objetivos da IA: tornar os computadores mais teis e
compreender os princpios que tornam a inteligncia possvel.
1.1Clssica (1956-1970)

Objetivo: simular a inteligncia humana


Mtodos: solucionadores gerais de problemas e lgica
Motivo do fracasso: subestimao da complexidade computacional dos
problemas
1.2 Romntica (1970-1980)

Objetivo: simular a inteligncia humana em situaes pr-determinadas.


Mtodos: formalismos de representao de conhecimento adaptados ao tipo
de

problema,

mecanismos

de

ligao

procedural

visando

maior

eficincia

computacional.
Motivo do fracasso: subestimao da quantidade de conhecimento
necessria para tratar mesmo o mais banal problema de senso comum.
1.3 Moderna (1980-1990)

Objetivo: simular o comportamento de um especialista humano ao resolver


problemas em um domnio especfico.

Mtodos: Sistemas de regras, representao da incerteza, conexionismo.


Motivo do fracasso: subestimao da complexidade do problema de
aquisio de conhecimento.

1.4 Clssica

Inicialmente, a pesquisa em manipulao de smbolos se concentrou no


desenvolvimento de formalismos gerais capazes de resolver qualquer tipo de
problemas. O sistema GPS, General Problem Solver, projetado por Ernst e Newell,
um exemplo deste tipo de pesquisa. Estes esforos iniciais ajudaram a estabelecer os
fundamentos tericos dos sistemas de smbolos e forneceram rea da IA uma srie
de tcnicas de programao voltadas manipulao simblica, por exemplo, as
tcnicas de busca heurstica. Os sistemas gerais desenvolvidos nesta poca
obtiveram resultados interessantes, por vezes at impressionantes, mas apenas em
domnios simplificados, onde o objetivo era principalmente a demonstrao da tcnica
utilizada, e no a soluo de um problema real. O problema com os sistemas gerais
que a sua extenso a domnios de problemas reais se mostrou invivel. Isto se deveu
a duas razes, uma relacionada com caractersticas tericas dos mtodos utilizados,
e outra associada natureza do conhecimento do mundo real.
A razo terica consequncia do uso, nos sistemas gerais, de modelos
baseados em lgica de primeira ordem como formalismo bsico. A utilizao desses
modelos leva chamada exploso combinatria: a memria e o tempo necessrios
para resolver um determinado problema crescem exponencialmente com o tamanho
do problema. Este problema, descrito por Cook em seu artigo The complexity of
theorem proving procedures, inerente aos mtodos baseados em lgica,
independentemente das tcnicas de programao utilizadas. A segunda razo est
associada ao fato de que, freqentemente, o conhecimento disponvel sobre o mundo
real incompleto e parcialmente incoerente, e que por vezes a nica forma de
soluo conhecida para determinados problemas reais consiste em uma srie de
regras prticas no fundamentadas por nenhum tipo de teoria geral do domnio que
pudesse ser usada para orientar a soluo.

Esta situao levou a dois tipos diferentes de soluo: (i) uso de mtodos
formais de inferncia mais fracos do que a lgica de primeira ordem que garantissem
certa eficincia aos programas, por exemplo, lgicas multivalores, e linguagens
terminolgicas. Desenvolveram-se mtodos heursticos e lgicas no convencionais
para permitir a representao de crenas, incoerncias e incompletudes, por exemplo,
lgica modal, lgica de excees e lgica nebulosa.
1.5 Romntica

Durante a dcada de setenta, a IA estava praticamente restrita ao ambiente


acadmico. Os objetivos da pesquisa eram, principalmente, a construo de teorias e
o desenvolvimento de programas que verificassem estas teorias para alguns poucos
exemplos. interessante notar que o fato de que no havia interesse em construir
programas de IA ``de verdade'', isto , com aplicaes prticas, no se deve a uma
eventual incompetncia em programao dos pesquisadores em IA. Pelo contrrio, foi
a inspirao desses ``hackers'' que levou a conceitos hoje integrados cincia da
computao, como: tempo compartilhado, processamento simblico de listas,
ambientes de desenvolvimento de ``software'', orientao objeto, etc., alm da
mudana da relao usurio-computador ao eliminar a intermediao de um operador
e colocar cada usurio diante de sua estao de trabalho.
Uma mudana importante ocorreu ao longo da dcada de setenta em
relao aos critrios acadmicos de julgamento de trabalhos em IA: houve uma
crescente exigncia de formalizao matemtica. Se no incio dos anos setenta, um
programa, mesmo tratando de alguns poucos exemplos de um problema at ento
no tratado, j era considerado IA, isto no acontecia mais em 1980. O programa em
si passou a ser a parte menos importante; a anlise formal da metodologia, incluindo
decidibilidade, completude e complexidade, alm de uma semntica bem fundada,
passou a ser o ponto fundamental. A dcada de setenta marcou tambm a passagem
da IA para a ``vida adulta'': com o aparecimento dos primeiros SE's, a tecnologia de IA
passou a permitir o desenvolvimento de sistemas com desempenho intelectual
equivalente ao de um ser humano adulto, abrindo perspectivas de aplicaes
comerciais e industriais.

1.6 Moderna

A tecnologia de SE disseminou-se rapidamente e foi responsvel por mais


um dos episdios ligados a promessas no cumpridas pela IA: o sucesso dos
primeiros SE's chamou a ateno dos empresrios, que partiram em busca de um
produto comercializvel que utilizasse esta tecnologia. No entanto, um SE no era um
produto: um produto, na viso dos empresrios, no deveria ser um sistema
especfico para um dado problema, mas algo que fosse implementado uma nica vez
e vendido em 100.000 unidades, por exemplo, uma ferramenta para a construo de
sistemas especialistas (ASE) . Com isso foram colocadas no mercado uma grande
quantidade de ASE's que prometiam solucionar o problema de construo de SE's. A
conseqncia foi uma grande insatisfao por parte dos usurios, pois, apesar de
uma ferramenta de programao adequada ajudar muito a construir um sistema
complexo, saber o que programar continua sendo o ponto mais importante.
Se os ASE's deveriam ser vendidos como produtos de IA, ento em algum
lugar deveria haver IA, e o lugar escolhido foi o motor de inferncia , que passou a
ser considerado como sinnimo de IA. Isto levou iluso de que para construir um SE
bastaria comprar um ASE, enquanto que a verdade que a IA em um SE est
basicamente na forma como representado o conhecimento sobre o domnio, isto ,
onde a IA sempre esteve: na tentativa de entender o comportamento inteligente a ser
modelado, no caso o comportamento do especialista ao resolver um problema. Uma
outra conseqncia desta viso distorcida dos ASE's foi a pouca nfase dada
inicialmente aquisio de conhecimento , certamente a parte mais difcil do
desenvolvimento de um SE. Se exageros existiram na publicidade dos ASE's, por
certo houve tambm trabalhos descrevendo com fidelidade o potencial e as limitaes
da nova tecnologia.
Atualmente, os ASE's so considerados como parte de uma tecnologia de
desenvolvimento de ``software'' estabelecida, sendo objeto de diversas conferncias
internacionais e submetida a avaliaes rigorosas de desempenho. Entre os diversos
benefcios associados ao desenvolvimento de SE's podem-se citar: distribuio de
conhecimento especializado, memria institucional, flexibilidade no fornecimento de
servios (consultas mdicas, jurdicas, tcnicas, etc.), facilidade na operao de
equipamentos, maior confiabilidade de operao, possibilidade de tratar situaes a

partir de conhecimentos incompletos ou incertos, treinamento, entre outros.


Atualmente, existem milhares de SE's em operao nos mais variados domnios, e a
influncia da IA em outros campos da computao, como engenharia de ``software'',
bancos de dados e processamento de imagens vem crescendo constantemente.
As principais reas de pesquisa em IA simblica so atualmente: sistemas
especialistas,

aprendizagem,

representao

de

conhecimento,

aquisio

de

conhecimento, tratamento de informao imperfeita, viso computacional, robtica,


controle inteligente, inteligncia artificial distribuda, modelagem cognitiva, arquiteturas
para sistemas inteligentes, linguagem natural e interfaces inteligentes. Alm das
linhas conexionista e simblica, observa-se hoje o crescimento de uma nova linha de
pesquisa em IA, baseada na observao de mecanismos evolutivos encontrados na
natureza, tais como a auto-organizao e o comportamento adaptativo. Nesta linha,
os modelos mais conhecidos so os algoritmos genticos e os autmatos celulares.
A gradativa mudana de metas da IA, desde o sonho de construir uma
inteligncia artificial de carter geral comparvel do ser humano at os bem mais
modestos objetivos atuais de tornar os computadores mais teis atravs de
ferramentas que auxiliam as atividades intelectuais de seres humanos, coloca a IA na
perspectiva de uma atividade que praticamente caracteriza a espcie humana: a
capacidade de utilizar representaes externas, seja na forma de linguagem, seja
atravs de outros meios. Deste ponto de vista, a computao em geral e a IA em
particular so o ponto culminante de um longo processo de criao de representaes
de conhecimento, iniciado com as primeiras pinturas rupestres. Esta nova perspectiva
coloca os programas de IA como produtos intelectuais no mesmo nvel dos demais,
ressaltando questes cuja importncia central para os interesses atuais da IA, por
exemplo, como expressar as caractersticas individuais e sociais da inteligncia
utilizando computadores de maneira a permitir uma maior produtividade, e como as
propriedades das representaes utilizadas auxiliam e moldam o desenvolvimento de
produtos intelectuais.

2.0 GRAFOS EM LINGUAGEM DE PROGRAMAO C

Grafos um conjunto no-vazio de vrtices e arestas, tais que cada arco


conecta dois ns, ou seja G(V,A). De forma mais simples, um grafo um conjunto de
pontos e arcos, e esses arcos conectam esses pontos (ou ns).

Ento dividimos assim o estudo dos grafos:

Grafo no direcionado:
Registro;
Main;
Menu;
Insero das Arestas;
Impresso da lista de adjacncia;
Busca em largura;
Busca em profundidade;

Para o garfo direcionado, a nica coisa que mudar ser a insero das
arestas, voc utilizara somente o primeiro teste que demonstrado na funo.
2.1 Registro
O registro onde ficara as informaes sobre o que cada espao de
memria ter que armazenar. Em relao ao registro voc pode utilizar duas formas
simples, uma consiste em apenas um espao de memria de um ponteiro para uma
lista de encadeada, o outro armazenar no s um ponteiro mais tambm qual ponto
aquele. Daremos nfase somente a que possui dois campos, pois sua lista de
adjacncia ser do mesmo tipo que ela, logo no precisaremos criar outro registro.
Registro com dois campos. Um para guardar o ponto do grafo e outro um
ponteiro para uma lista de adjacncia, lista de adjacncia so todos os pontos para
qual aquele ponto est ligado:
typedef struct x{
int num;
struct x *prox;
}x;

Aqui chamamos o tipo abstrato de dado de x, mas voc pode colocar o


nome que desejar. O registro consiste somente nisso. Mas como trabalhamos com
busca em largura e em profundidade teremos mais alguns registros, um ser utilizado
na busca em profundidade e ambos sero utilizados na busca em largura.
typedef struct pilha{
int num;
struct pilha *prox;
}pilha;

Esse registro ser utilizado em ambas as buscas, vale lembrar que a busca
em profundidade trabalha com a ideia da pilha (LIFO) o primeiro que entra o ltimo
a sair, e a busca em largura trabalha coma ideia da fila (FIFO) o primeiro que entra
o primeiro que sai.
typedef struct sentinela{
struct pilha *inicio;
struct pilha *fim;
}sentinela;

A sentinela, caso voc no lembre, guarda o incio e o final da fila, e com o


auxlio dela que trabalharemos a busca em largura.
2.2 Main
Na main criaremos o ponteiro para o grafo, pois at agora no sabemos o
tamanho dele, digo-lhes que muito mais prtico fazer um grafo dinamicamente, caso
contrrio toda vez que seu professor mudar o tamanho do grafo voc ter que alterar
seu cdigo.
Nela havemos de ler do usurio o tamanho do grafo, ou seja, quantos pontos
ele possui, e chamamos a funo menu, que ficara encarregada da continuao do
algoritmo.
Vejamos a Main:
int main(){
x *grafo=NULL;

Criao do ponteiro para o grafo

int tam;
printf("Tamanho do vetor: ");
scanf("%d",&tam);

grafo=(x *)malloc(tam * sizeof(x));

Leitura do tamanho do grafo

Alocao do Grafo

Teste para verificar

if(!grafo){
puts("ERRO\n");system("pause");exit(0);

Se o espao de memoria
Foi alocado

}
system("cls");

menu(grafo,tam);

Chamada da funo menu

2.3 Menu
A funo menu, consiste apenas em inicializar todos os campos do nosso
grafo e ler do usurio qual a opo desejada e a parti da chamar as funes
correspondente a escolha.
void menu(x *grafo, int tam){
int op,i;

for(i=0;i<tam;i++){
grafo[i].num=i;

Inicializao dos campos do nosso grafo

grafo[i].prox=NULL;
}
system("cls");

do{
printf("\t 1 - Inserir Arestas\n");
printf("\t 2 - Imprimir\n");
printf("\t 3 - Busca em Profundidade\n");
printf("\t 4 - Busca em Largura\n");
printf("\t 5 - Sair\n\n");
printf("Opcao: ");
scanf("%d",&op);

Leitura da opo do usuario

Imprime as
Opes

switch(op){
case 1: grafo=insere_aresta(grafo,tam);break;
case 2: imprime(grafo,tam);break;
Chama a funo

case3: busca_em_prof(grafo,tam,grafo[0].num);break;

Correspondente
A escolha do usurio

case4: busca_largura(grafo,tam,grafo[0].num);break;
case 5:exit(0);break;
default: printf(erro);break;

}
system("pause");
system("cls");
}while(op!=5);
}

Na funo menu recebemos um ponteiro para o grafo e o tamanho do grafo,


utilizamos esse mtodo de receber o tamanho do grafo por parmetro para que no
ocorra o caso de excedermos o tamanho do grafo e consequentemente ocasionar um
erro gravssimo. Feito isso as funes so chamadas segundo a ordem do usurio.

2.4 Insero das Arestas


O objetivo desta funo criar uma lista de adjacncia, lista de adjacncia
so todas as arestas que partem, ou chegam em determinado ponto (ou n), voc
deve ter estudado isso ou em estrutura de dados avanada ou em matemtica.
Assim como na funo menu, recebemos um ponteiro para o garfo, e o valor
do tamanho do grafo justificado anteriormente. Depois disso lemos do usurio os dois
pontos, isso que ir dizer ao programa, de onde parte a aresta e qual o seu
extremo.
Para entendermos melhor vamos olhar a imagem do incio da apostila.
1 ponto,
de onde
parte a
aresta

Essa aresta que


vamos inserir, o
ponto 1 liga o
ponto 2

Ok, depois de lermos o primeiro e o segundo ponto, vamos inserir a lista de


adjacncia, a lista de adjacncia ser explicada a imagem 2
abaixo.
Possumos
nosso
ponto,
o
grafo, e a lista de adjacncia ser uma lista encadeada comlimite
todosdaos pontos para
qual aquele ponto est ligado. Para explicar, usamos como exemplo,
aresta um grafo com
quatro pontos, vamos explica-lo e em seguida mostrar sua lisa de adjacncia.

0
3

Comeamos por 0 porque como usamos um vetor, vetor em C sempre


comea do zero. Aqui o ponto 0 liga o ponto 1, 2 e 3, como no um grafo
direcionado, ento os pontos 1,3 e 2 tambm apontam para o ponto 0.

0
3

A lista de adjacncia do ponto 0 ser todos esses pontos que ele est ligado,
mas como no direcionado, esses pontos tambm vo apontar para o ponto 0
0
1

1
0
0
0

2
3

Agora, vamos fazer a lista de adjacncia do ponto 1, o ponto 1 aponta


para o ponto 0, 2 e 3, mas observe na lista que o ponto 1 j possui o 0 na lista
de adjacentes, ento no necessrio repeti-lo. Apenas coloca-se os novos.

0
1
2

3
0

0
3

Como no um grafo direcionado, esses pontos tambm apontam para o


ponto 1.

0
1
2
3

Agora, vamos fazer a lista de adjacncia do ponto 2. O ponto 2 aponta para


o ponto 0, 1 e 3, mas observe na lista que o ponto 2 j possui o 0 e 1 na lista de
adjacentes, ento no necessrio repeti-lo. Apenas coloca-se os novos.

1
2
3

0
3

Como no um grafo direcionado, esses pontos tambm apontam para o


ponto 2. Todavia o ponto 2 j est na lista de adjacentes dos outros pontos, exceto do
ponto 3, logo ser o nico lugar que necessrio inseri-lo.
0

3
3

2
3

Observe que a lista est completa, se fossemos conferir as arestas do grafo


verificaramos que conclumos a lista de adjacentes.
A funo de insero de arestas, ou lista de adjacentes, depois de ler dois
nmeros do usurio, que so os pontos, faz dois testes, ele verifica se esses
nmeros so iguais, quando ocorre este caso, o ponto aponta para ele prprio, se
essa condio for verdadeira alocamos apenas um espao de memria, e fazemos
o grafo na posio daquele nmero receber um novo elemento com o seu prprio
valor.
if(n1==n2){
novo=(x *)malloc(sizeof(x));
novo->num=n2;
novo->prox=NULL;
novo->prox=grafo[n1].prox;
grafo[n1].prox=novo;

Recebe a lista de adjacentes daquela


posio
Recebe o novo elemento
da lista

Caso contrrio, ele aloca dois espaos em memria, um para cada nmero,
lembrando novamente de que como no um grafo direcionado, ambos apontam
para ambos.
else{
novo=(x *)malloc(sizeof(x));
novo->prox=NULL;
novo->num=n2;
novo->prox=grafo[n1].prox;
grafo[n1].prox=novo;

out=(x *)malloc(sizeof(x));
out->prox=NULL;
out->num=n1;
out->prox=grafo[n2].prox;
grafo[n2].prox=out;
}

Depois de feito isso, a funo retorna o grafo, com a lista de adjacentes


alterada.
return grafo;

Funo completa:
x *insere_aresta(x *grafo, int tam){
int n1,n2,i;
x *novo, *out;
x *aux;
printf("Insira a aresta\n");
printf("1 Ponto: ");
scanf("%d",&n1);
printf("2 Ponto: ");
scanf("%d",&n2);

if(n1==n2){
novo=(x *)malloc(sizeof(x));
novo->num=n2;
novo->prox=NULL;
novo->prox=grafo[n1].prox;
grafo[n1].prox=novo;
}
else{
novo=(x *)malloc(sizeof(x));
novo->prox=NULL;
novo->num=n2;
novo->prox=grafo[n1].prox;
grafo[n1].prox=novo;

out=(x *)malloc(sizeof(x));
out->prox=NULL;
out->num=n1;
out->prox=grafo[n2].prox;
grafo[n2].prox=out;
}
printf("\n\tOK\n\n");
return grafo;
}

2.5 Impresso da lista de adjacentes

Essa uma funo simples e pequena, ela consiste em receber por


parmetro um ponteiro para o grafo, e a criao de uma varivel auxiliar que
percorrer toda a lista de adjacente imprimindo todos os valores enquanto a lista
no for vazia, ele percorre todas as posies do vetor do grafo, imprimindo toda a
lista.

void imprime(x *grafo, int tam){


x *aux;
int i;
for(i=0;i<tam;i++){
printf("Lista do Numero: %d :",grafo[i].num);
if(grafo[i].prox==NULL)
continue;
aux=grafo[i].prox;
while(aux!=NULL){
printf(" ->%d",aux->num);
aux=aux->prox;
}
puts("\n\n");
}
}

Essa funo funciona assim, pegamos a primeira posio do vetor, e sua


lista de adjacente. Vamos ver um exemplo com apenas trs pontos.
0
1
posi
o

1
2

Depois de pegarmos essa posio, uma varivel auxiliar recebe a lista de


adjacncia.
au
x

Posi
o atual

A funo ira imprimir o valor que est na varivel auxiliar, depois passar
para a prximo da lista de adjacncia, at que o prximo seja nulo, quando isso
ocorrer a funo passar para a prxima posio do grafo, se ele estava na
posio 0 vai para 1, se estava na 1 vai para a posio 2 assim sucessivamente,
at que tenha imprimido todas as posies do grafo.

2.6 Busca em largura

Para utilizamos a busca em largura, precisamos de duas funes que so


encarregadas do controle da busca, so elas insere_fila e desenfila aqui
utilizaremos ambos os registros mostrados no incio desta apostila.
Vejamos a funo de insere fila:
sentinela *insere_fila(sentinela *sent, int num){
pilha *aux=(pilha *)malloc(sizeof(pilha));
aux->num=num;
aux->prox=NULL;
if(sent->fim==NULL){
sent->inicio=aux;
sent->fim=aux;
}else{
sent->fim->prox=aux;
sent->fim=aux;
}
return sent;
}

Recebemos por parmetro a nossa sentinela que contm o incio e o fim da


fila, e o nmero que deseja-se inserir na fila. A parti da aloca-se um espao de
memria para o novo elemento. Verifica se o fim da fila vazio, se for, significa que
a fila est vazia, ento tanto o incio e o fim da sentinela receberam o mesmo valor.

Caso contrrio o prximo do fim (sent->fim->prox) receber o novo elemento, e


atualizamos o ltimo elemento da fila.
Vejamos a funo desenfila:
sentinela *desenfila(sentinela *fila){
pilha *aux;
if(fila->inicio == fila->fim){
free(fila->inicio);
fila->inicio=NULL;
fila->fim=NULL;
} else{
aux=fila->inicio;
fila->inicio=fila->inicio->prox;
free(aux);
}
return fila;
}

Tambm recebemos a sentinela por parmetro, a parti da so testes.


Verificamos se o inicio e o fim da sentinela so iguais, se forem porque a fila s
tem um elemento, ambos ento recebem o valor nulo, seno, utiliza-se um auxiliar
para receber o incio da fila, e passa o incio para o prximo elemento, em seguida
libera-se a memria da varivel auxiliar que contm o antigo incio da fila.
Agora vejamos a funo de busca em largura:
Recebemos por parmetro trs dados: o ponteiro para o grafo, o tamanho do
grafo, e o incio, que nele que obtemos a informao de onde iniciar a busca em
largura. Alocamos a sentinela, e inicializamos seus campos. Criamos um vetor
chamado visitado para manter o controle de quais elemento j foram visitados para
que no o fiquemos repetindo.
Logo de incio chamamos a funo para inserir na fila o incio que foi
escolhido pelo usurio. Em seguida entramos no principal loop do programa, sua
condio enquanto o fim da sentinela for diferente de vazio, while(sent->fim!
=NULL). Ento em uma varivel receber o nmero que est no incio da fila e
desalocamos o incio da fila, e verifica se o vetor de visitado naquela posio
diferente de 0, se for colocamos o valor 1 nele, o 1 significa que ele j foi visitado.
Imprimimos esse valor, pronto j comeamos a busca em largura.

Uma varivel auxilia vai receber a lista de adjacncia daquela posio do


grafo. Entramos ento no prximo teste da funo, enquanto a varivel auxiliar for
diferente de nulo, while(aux!=NULL). Enquanto essa condio no verdadeira
verificamos se o vetor de visitados na posio que h no campo nmero da varivel
auxiliar j foi visitado if(visitados[aux->num]!=1), se ele ainda no foi
visitado, a funo insere_fila chamada, enviando o valor da varivel auxiliar que
est caminhando na lista adjacente.

void busca_largura(x *grafo, int tam, int inicio){


int visitados[tam];
sentinela *sent=(sentinela *)malloc(sizeof(sentinela));
sent->inicio=NULL;
sent->fim=NULL;
int i,pos,y;
x *aux;
Aloca o
sentinel
ae
inicializa
os

for(i=0;i<tam;i++){
visitados[i]=0;

Inicializa o vetor de
visitados

sent=insere_fila(sent,inicio);

while(sent->fim!=NULL){
pos=sent->inicio->num;
sent=desenfila(sent);
if(visitados[pos]!=1){
visitados[pos]=1;
printf(" %d ",pos);
}
aux = grafo[pos].prox;
while(aux!=NULL){
if(visitados[aux->num]!=1){

Insere na
fila

y=aux->num;
sent=insere_fila(sent,y);
}

Insere na
fila

aux=aux->prox;
}
}
}

2.7 Busca em profundidade

A busca em profundidade semelhante a busca em profundidade,


aqui no utilizaremos a sentinela, vamos utilizar somente a pilha. Tambm
utilizaremos duas funes, a empilha e desempilha.

pilha *empilha(pilha *p, int num){


pilha *aux=(pilha *)malloc(sizeof(pilha));
aux->num=num;
if(p!=NULL)
aux->prox=p;
else
aux->prox=NULL;
return aux;
}

Essa funo simples, recebe um ponteiro para a pilha, aloca um espao em


memria, e faz dois testes simples: verifica se a pilha no est vazia, se sim, o
novo valor no campo prximo receber o incio da pilha, seno o auxiliar
considerado instantaneamente o incio da pilha.

pilha *desempilha(pilha *p){

pilha *aux=p;

p=p->prox;
free(aux);
return p;
}

A funo desempilha simplesmente passa o incio da pilha para o prximo


elemento e libera a memria.
A busca em profundidade idntica a funo de busca em largura, somente
alguns detalhes foram retirados.
void

busca_em_prof(x *grafo, int tam, int inicio){

int visitados[tam];
pilha *p=NULL;
int i,pos,y;
x *aux;

for(i=0;i<tam;i++){
visitados[i]=0;

Inicializa o vetor de
visitados

p=empilha(p,inicio);
while(p!=NULL){
pos=p->num;
p=desempilha(p);
if(visitados[pos]!=1){
visitados[pos]=1;
printf(" %d ",pos);
}

Insere na
fila

aux = grafo[pos].prox;
while(aux!=NULL){
if(visitados[aux->num]!=1){
y=aux->num;
p=empilha(p,y);
}

Insere na
pilha

aux=aux->prox;
}
}
}

Toda ideia logica das buscas em profundidade e largura so as


mesmas.

2.8 Cdigo completo Grafo


#include<stdio.h>
#include<stdlib.h>
/************************************************************/
typedef struct x{
int num;
struct x *prox;
}x;

typedef struct sentinela{


struct pilha *inicio;
struct pilha *fim;
}sentinela;

typedef struct pilha{


int num;

struct pilha *prox;


}pilha;
/************************************************************/
char erro[]={"Opcao Invalida!\n"};

/************************************************************/
void menu(x *grafo, int tam);
x *insere_aresta(x *grafo, int tam);
void imprime(x *grafo, int tam);
void busca_em_prof(x *grafo, int tam, int inicio);
pilha *desempilha(pilha *p);
pilha *empilha(pilha *p, int num);
sentinela *insere_fila(sentinela *filas, int num);
sentinela *desenfila(sentinela *filas);
void busca_largura(x *grafo, int tam, int inicio);
/************************************************************/
int main(){
x *grafo=NULL;
int tam;

printf("Tamanho do vetor: ");


scanf("%d",&tam);

grafo=(x *)malloc(tam * sizeof(x));

if(!grafo){
puts("ERRO\n");system("pause");exit(0);
}
system("cls");

menu(grafo,tam);
}
/************************************************************/
void menu(x *grafo, int tam){

int op,i;

for(i=0;i<tam;i++){
grafo[i].num=i;
grafo[i].prox=NULL;
}
system("cls");

do{
printf("\t 1 - Inserir Arestas\n");
printf("\t 2 - Imprimir\n");
printf("\t 3 - Busca em Profundidade\n");
printf("\t 4 - Busca em Largura\n");
printf("\t 5 - Sair\n\n");
printf("Opcao: ");
scanf("%d",&op);
switch(op){
case 1: grafo=insere_aresta(grafo,tam);break;
case 2: imprime(grafo,tam);break;
case 3: busca_em_prof(grafo,tam,grafo[0].num);break;
case 4: busca_largura(grafo,tam,grafo[0].num);break;
case 5:exit(0);break;
default: printf(erro);break;
}

system("pause");
system("cls");
}while(op!=5);
}
/************************************************************/

x *insere_aresta(x *grafo, int tam){

int n1,n2,i;
x *novo, *out;
x *aux;

printf("Insira a aresta\n");
printf("1 Ponto: ");
scanf("%d",&n1);
printf("2 Ponto: ");
scanf("%d",&n2);

if(n1==n2){
novo=(x *)malloc(sizeof(x));
novo->num=n2;
novo->prox=NULL;
novo->prox=grafo[n1].prox;
grafo[n1].prox=novo;
}
else{
novo=(x *)malloc(sizeof(x));
novo->prox=NULL;
novo->num=n2;

novo->prox=grafo[n1].prox;
grafo[n1].prox=novo;

out=(x *)malloc(sizeof(x));
out->prox=NULL;
out->num=n1;
out->prox=grafo[n2].prox;
grafo[n2].prox=out;
}
printf("\n\tOK\n\n");
return grafo;
}

/************************************************************/
void imprime(x *grafo, int tam){
x *aux;
int i;
for(i=0;i<tam;i++){
printf("Lista do Numero: %d :",grafo[i].num);
if(grafo[i].prox==NULL)
continue;
aux=grafo[i].prox;
while(aux!=NULL){
printf(" ->%d",aux->num);
aux=aux->prox;
}
puts("\n\n");
}
}

/************************************************************/
pilha *empilha(pilha *p, int num){
pilha *aux=(pilha *)malloc(sizeof(pilha));
aux->num=num;
if(p!=NULL)
aux->prox=p;
else
aux->prox=NULL;
return aux;
}

/************************************************************/
pilha *desempilha(pilha *p){
pilha *aux=p;

p=p->prox;
free(aux);
return p;
}
/************************************************************/
void

busca_em_prof(x *grafo, int tam, int inicio){

int visitados[tam];
pilha *p=NULL;
int i,pos,y;
x *aux;

for(i=0;i<tam;i++){
visitados[i]=0;
}

p=empilha(p,inicio);
while(p!=NULL){
pos=p->num;
p=desempilha(p);
if(visitados[pos]!=1){
visitados[pos]=1;
printf(" %d ",pos);
}
aux = grafo[pos].prox;
while(aux!=NULL){
if(visitados[aux->num]!=1){
y=aux->num;
p=empilha(p,y);
}
aux=aux->prox;
}
}
}
/************************************************************/
sentinela *insere_fila(sentinela *sent, int num){
pilha *aux=(pilha *)malloc(sizeof(pilha));
aux->num=num;
aux->prox=NULL;

if(sent->fim==NULL){
sent->inicio=aux;
sent->fim=aux;
}else{

sent->fim->prox=aux;
sent->fim=aux;
}
return sent;
}
/************************************************************/
sentinela *desenfila(sentinela *fila){
pilha *aux;

if(fila->inicio == fila->fim){
free(fila->inicio);
fila->inicio=NULL;
fila->fim=NULL;
} else{
aux=fila->inicio;
fila->inicio=fila->inicio->prox;
free(aux);
}
return fila;
}
/************************************************************/
void busca_largura(x *grafo, int tam, int inicio){
int visitados[tam];
sentinela *sent=(sentinela *)malloc(sizeof(sentinela));
sent->inicio=NULL;
sent->fim=NULL;
int i,pos,y;
x *aux;

for(i=0;i<tam;i++){
visitados[i]=0;
}

sent=insere_fila(sent,inicio);
while(sent->fim!=NULL){
pos=sent->inicio->num;
sent=desenfila(sent);
if(visitados[pos]!=1){
visitados[pos]=1;
printf(" %d ",pos);
}
aux = grafo[pos].prox;
while(aux!=NULL){
if(visitados[aux->num]!=1){
y=aux->num;
sent=insere_fila(sent,y);
}
aux=aux->prox;
}
}
}

3. RESOLUO DE PROBLEMAS POR MEIO DE BUSCA


3.1 Agentes de resoluo de problemas
Agentes reativos no funcionam em ambientes para quais o nmero de regras
condio-ao grande demais para armazenar.
Nesse caso podemos construir um tipo de agente baseado em objetivo
chamado de agente de resoluo de problemas.

3.2 Busca
Um agente com vrias opes imediatas pode decidir o que fazer comparando
diferentes sequncias de aes possveis.
Esse processo de procurar pela melhor sequncia chamado de busca.

Formular objetivo buscar executar

Exemplo: Romnia

De frias na Romnia; atualmente em Arad.

Vo sai amanh de Bucareste.

Formular objetivo:
Estar em Bucareste

Formular problema:
estados: cidades
aes: dirigir entre as cidades

Encontrar soluo:
sequncia de cidades, ex., Arad, Sibiu, Fagaras, Bucareste.

3.3 Formulao de problemas


Um problema definido por quatro itens:
1.

Estado inicial ex., em Arad"

2.

Aes ou funo sucessor S(x) = conjunto de pares estado-

ao

3.

4.

ex., S(Arad) = {<Arad Zerind, Zerind>, }

Teste de objetivo, pode ser

explcito, ex., x = em Bucharest"

implcito, ex., Cheque-mate(x)

Custo de caminho (aditivo)

ex.,

soma

das

distncias,

nmero

de

aes

executadas, etc.

c(x,a,y) o custo do passo, que deve ser sempre 0

Uma soluo uma sequncia de aes que levam do

estado inicial para o estado objetivo.

caminho.

Uma soluo tima uma soluo com o menor custo de

Agente

de

soluo

de

Problemas

Supe que ambiente esttico, observvel, discreto e determinstico.

3.4 Espao de estados


O conjunto de todos os estados acessveis a partir de um estado inicial
chamado de espao de estados.

Os estados acessveis so aqueles dados pela funo

sucessora.
O espao de estados pode ser interpretado como um grafo em que os
ns so estados e os arcos so aes.
3.5 Selecionando um espao de estados
O mundo real absurdamente complexo
O espao de estados uma abstrao

Estado (abstrato) = conjunto de estados reais


Ao (abstrata) = combinao complexa de aes reais
ex., "Arad Zerind" representa um conjunto complexo de rotas,
desvios, paradas, etc.
Qualquer estado real do conjunto em Arad deve levar a algum
estado real em Zerind.
Soluo (abstrata) = conjunto de caminhos reais que so solues no
mundo real
A abstrao til se cada ao abstrata mais fcil de executar que o
problema original.

Exemplo 1: Espao de Estados do Mundo do Aspirador de P

Estados: Definidos pela posio do rob e sujeira (8 estados)


Estado inicial: Qualquer um
Funo sucessor: pode-se executar qualquer uma das aes em cada

estado (esquerda, direita, aspirar)


Teste de objetivo: Verifica se todos os quadrados esto limpos
Custo do caminho: Cada passo custa 1, e assim o custo do caminho
o nmero de passos do caminho

Exemplo 2: O quebra-cabea de 8 peas

Estados: Especifica a posio de cada uma das peas e do espao

vazio
Estado inicial: Qualquer um
Funo sucessor: gera os estados vlidos que resultam da tentativa de
executar as quatro aes (mover espao vazio para esquerda, direita,

acima ou abaixo)
Teste de objetivo: Verifica se o estado corresponde configurao

objetivo.
Custo do caminho: Cada passo custa 1, e assim o custo do caminho
o nmero de passos do caminho

Exemplo 3:Oito rainhas Formulao incremental

Estados: qualquer disposio de 0 a 8 rainhas

Estado inicial: nenhuma rainha


Funo sucessor: colocar 1 rainha em qualquer vazio
Teste: 8 rainhas no tabuleiro, nenhuma atacada
64x63x...57 = 3x1014 sequncias para investigar

Exemplo 3:Oito rainhas Formulao de estados completos

Estados: disposies de n rainhas, uma por coluna, nas n colunas mais

a esquerda sem que nenhuma rainha ataque outra


Funo sucessor: adicionar uma rainha a qualquer quadrado na coluna

vazia mais esquerda, de tal modo que ela no seja atacada


Tamanho do espao de estados: 2.057

3.6 Problemas do mundo real

Problema de roteamento
Encontrar a melhor rota de um ponto a outro (aplicaes: redes
de computadores, planejamento militar, planejamento de viagens
areas)

Problemas de tour
Visitar cada ponto pelo menos uma vez

Caixeiro viajante

Visitar cada cidade exatamente uma vez


Encontrar o caminho mais curto

Layout de VLSI
Posicionamento de componentes e conexes em um chip

Projeto de protenas
Encontrar uma sequncia de aminocidos que sero
incorporados em uma protena tridimensional para curar alguma
doena.

Pesquisas na Web
fcil pensar na Web como um grafo de ns conectados por links

3.7 Busca de solues

Idia: Percorrer o espao de estados a partir de uma rvore de busca.


Expandir o estado atual aplicando a funo sucessor, gerando novos

estados.
Busca: seguir um caminho, deixando os outros para depois.
A estratgia de busca determina qual caminho seguir.

Exemplo de rvore de busca

Figura 1 - Estado inicial

Figura 2 - Depois de expandir Arad

Figura 3 - Depois de expandir Sibiu

3.8 Descrio informal do algoritmo geral de busca em rvore

rvore de busca no equivalente a espao de estados!

H 20 estados no mapa da Romnia (espao de estados), mas infinitos


caminhos a percorrer. Portanto a rvore de busca, neste caso, tem
tamanho infinito.
Caminho infinito: Arad-Sibiu-Arad-Sibiu-Arad-...

3.9 Estados vs. Ns

Um estado uma (representao de) uma configurao fsica


Um n uma estrutura de dados que parte da rvore de busca e inclui
estado, n pai, ao, custo do caminho g(x), profundidade

4.0 Algoritmo geral de busca em rvore

4.1 Estratgias de busca

Uma estratgia de busca definida pela escolha da ordem da expanso

de ns
Estratgias so avaliadas de acordo com os seguintes critrios:
completeza: o algoritmo sempre encontra a soluo se ela existe?
complexidade de tempo: nmero de ns gerados
complexidade de espao: nmero mximo de ns na memria
otimizao: a estratgia encontra a soluo tima?

Complexidade de tempo e espao so medidas em termos de:


b: mximo fator de ramificao da rvore (nmero mximo de
sucessores de qualquer n)

d: profundidade do n objetivo menos profundo

m: o comprimento mximo de qualquer caminho no espao de


estados (pode ser )

Potrebbero piacerti anche