Você está na página 1de 24

Agentes

São sistemas/entidades que impactam o ambiente em que estão inseridos.


Podem ser:
Agente/agente racional – trata-se de uma entidade que impacta o ambiente em que
está inserido através de ações que tentam obter a solução/resultado mais eficiente
possível. Ex.:
Agente reflexo – São agentes (que podem ser racionais ou não) que atuam sem se
preocuparem com o impacto das suas ações no ambiente e que agem com base nos inputs
que recebem do ambiente.
Agente reflexo puro – são agentes/sistemas que atuam no ambiente de forma
automatizada, contudo aprendem com as respostas e adaptam-se a novos estímulos do
ambiente.
Agente reflexo vs. agente reflexo puro – o agente reflexo age de forma previsível, já
o agente reflexo puro adapta-se a novos estímulos e situações.
Agente reflexo puro vs. agente racional – o agente reflexo puro, embora se adapte a
novos estímulos tem respostas automatizadas, enquanto o agente racional “pensa e
pondera” as ações a tomar relativamente aos estímulos recebidos.
Agente planeador – São agentes que simulam várias ações e atuam de acordo com as
consequências das simulações, selecionando a melhor hipótese. Trata-se da forma mais
humanizada de agir pois é a que mais se aproxima do comportamento humano.

Nota importante: agentes reflexos podem ser agentes racionais porque podem
estar definidos para dar a resposta mais eficiente possível de forma
automatizada (segundo indicação da professora) – têm programadas todas as
opções possíveis e conseguem escolher a melhor ação relativamente ao que
pretendem.

Agentes baseados em modelos – utilizam os inputs recebidos do ambiente para simular


os resultados possíveis e tentam atuar de forma a modelar o ambiente em que estão
inseridos da forma mais eficiente possível.
Agentes baseados em objetivos – simulam todas as ações possíveis com base nos
inputs recebidos do ambiente e atuam da forma que consideram ser mais benéfica para
maximizar e alcançar os objetivos que têm.

Função de agente – é a função que determinado agente tem. Ex.: um agente que recebe
uma localização A e uma localização B e retorna o caminho a tomar entre A e B.
Programa de agente – é a implementação da função de agente. Podem existir vários
programas de agente para uma função de agente. Pegando no exemplo de cima: o
programa de agente 1 pode implementar a função de agente procurando o caminho que
apanhe mais paragens. Já o programa de agente 2 pode também implementar a função
de agente e procurar o caminho que é mais rápido (menos tempo).

Ambiente
É o meio em que os agentes estão inseridos e com o qual vão interagir e efetuar ações.
Podem ser:
• Parcialmente observáveis: o agente não tem informação total do ambiente e
necessita de estimar internamente o estado do restante ambiente. É o contrário de
um ambiente totalmente observável. Nos ambientes parcialmente observáveis, o
agente necessita de ter memória.
• Estocástico – uma ação pode ter múltiplos resultados diferentes e com
probabilidades também elas diferentes. É o contrário de um ambiente
determinístico, em que uma ação tem apenas um resultado garantido de acontecer.
Nos ambientes estocásticos, o agente necessita de estar preparado para
contingências.
• Multiagente – o ambiente é impactado por múltiplos agentes. Por esse motivo, o
agente precisa de randomizar as suas ações para não ser previsível.
• Estático – se o ambiente nunca se alterar. É o contrário de ambiente dinâmico,
em que o ambiente se modifica à medida que o agente vai atuando. Nos ambientes
estáticos, o agente tem mais tempo para computar uma decisão racional.
• Físicas conhecidas – quando o agente conhece a física do ambiente e pode usá-
la de imediato para atuar. Caso não tenha físicas conhecidas, é necessário haver
exploração do agente para ele saber como pode atuar no ambiente (atuar
deliberadamente para saber quais são os resultados).
• Discretos – um ambiente é considerado discreto quando o seu conjunto de
resultados possível está bem definido.

Exemplos:
Ambientes de agente único:
• Pacman (se os fantasmas seguirem sempre caminhos fixos. Caso contrário é
multiagente)
• Palavras cruzadas (o jogador não precisa de randomizar os seus atos)
• Robot que tira bolachas deformadas de uma linha

Ambiente estático:
• Palavras cruzadas
Ambiente discreto:
• Pedra-papel-tesoura
• Palavras cruzadas

Espaço de estados (Space States) e problemas de procura (Search


problems)
Search problem – Consiste na formulação que permite representar o ambiente, o agente,
os estados e as ações para atingir o objetivo. Estes problemas são constituídos pelos
seguintes elementos:
• Estado – trata-se da representação do ambiente num dado momento. Pode
referenciar várias variáveis que possam ser relevantes (posição do agente, p.e.).
• Espaço de estados – são todos os estados possíveis num determinado ambiente.
• Transição (ou transição de modelo) – É o output gerado após ser efetuada uma
determinada ação.
• Custo (de ação) – é o custo de passar de um estado para outro após efetuar uma
ação.
• Estado inicial – é o estado em que o agente inicia a sua existência.
• Teste objetivo – é uma função de verificação se um determinado estado é o
estado que se pretende atingir.
• Plano – corresponde ao percurso de ações desde o estado inicial até um
determinado estado (pode ser até um beco sem saída, p.e.).
• Solução – é a implementação de uma sequência de ações que chega ao estado
objetivo (podem existir várias soluções para o mesmo problema).
• Solução ótima – é a solução que tem o menor custo entre todas as soluções.

World state (estado do mundo/ambiente) vs. Search state (estado de procura)


O world state tem toda a informação relacionada com um determinado estado.
O search state tem apenas a informação necessária para planear o próximo estado (por
questões de eficiência principalmente)

State space size (tamanho do espaço de estados) - Corresponde ao número total de


estados distintos que podem existir.

Grafos de espaço de estados (State Space Graphs) e árvores de


busca (Search Trees)
Grafos de espaço de estado – representam, através de nós (que são estados)
interligados por arestas/ligações/arcos direcionadas (que representam ações). Estas
arestas podem ter pesos associados que são considerados os custos das ações. São muito
pesados para armazenar em memória, sendo mais utilizados em termos concetuais para
analisar e resolver o problema. Num grafo, um estado é representado apenas uma vez o
que ajuda a avaliar problemas de busca.
Árvores de busca – consistem numa representação em árvore dos estados, em que
cada ramo representa um plano possível. Contrariamente ao grafo, os nós podem aparecer
várias vezes, consoante o número de vezes que sejam referenciados. As árvores são iguais
ou maiores que os seus grafos correspondentes uma vez que existe a possibilidade de
repetir estados.

Nota: Em ambos os casos, é possível entrar em ciclos infinitos, bastando para


isso que haja uma ligação recíproca entre dois nós.

Pesquisa não informada (Uninformed search)


É um tipo de pesquisa que apenas utiliza as ações possíveis e o estado atual para procurar
as soluções possíveis, sem recorrer a informações heurísticas ou adicionais.

Propriedades dos algoritmos de procura


Completude (Completeness) – O algoritmo será capaz de encontrar uma solução para
o problema se ela existir? (assumindo que podem ser dados infinitos recursos)
Otimização (Optimality) – O algoritmo será capaz de encontrar a solução mais eficiente
(menor custo) para um estado objetivo?
Fator de branching (Branching factor) – O número de nós que surgem sempre que
um nó de procura é expandido.
Profundidade máxima (m) – É a profundidade máxima que pode ser alcançada na
pesquisa.

Algoritmos de procura não informada (Search alghoritms)


DFS – Depth First Search (procura em profundidade)
• É uma estratégia de procura que tenta obter sempre o máximo de nós possíveis.
• Funciona com uma lógica LIFO (last in first out)
• Procura em profundidade, expandindo os nós filhos
• Quando encontra o objetivo pára e verifica os restantes ramos
• O DFS não pára quando encontra uma solução. Ele continua e avalia todas as
hipóteses.
• Alterar os pesos das arestas não tem impacto no seu resultado.
Completude: O DFS não é completo e podem existir loops com ramos infinitos. É bastante
completo quando se trata de um espaço de estados finito.
Otimização: Não é ótimo porque procura sem se preocupar com custos.
Complexidade temporal: Na pior das hipóteses, pode procurar a árvore toda para
encontrar a solução.
Complexidade de espaço: O DFS apenas explora uma subárvore de um nó de cada vez.

Busca em profundidade iterativa

A busca em profundidade iterativa é uma variação da busca em profundidade (DFS) que


itera em diferentes profundidades, aumentando gradualmente a profundidade máxima
explorada. Ela explora primeiro os nós mais profundos e depois retrocede.

Completude - A busca em profundidade iterativa é completa se o espaço de busca for


finito. Ela eventualmente explora todos os nós e encontra uma solução, desde que haja
uma solução.
Otimização - A busca em profundidade iterativa não é ótima. Ela encontra a primeira
solução que atinge a profundidade máxima explorada, que pode não ser a solução ótima.
Complexidade temporal - O custo de tempo da busca em profundidade iterativa
depende da profundidade máxima explorada. Se a profundidade máxima for muito grande,
o custo de tempo pode ser elevado.
Complexidade de espaço – A busca em profundidade iterativa mantém apenas os nós
do caminho atual em memória, o que a torna eficiente em termos de uso de memória.

BFS – Breadth-First Search (procura em largura)


• É uma estratégia de procura que tenta obter sempre o caminho mais curto até ao
objetivo.
• Funciona com uma lógica FIFO (first in first out).
• Procura lateralmente, avaliando os nós que se encontram ao mesmo nível e só
depois expandindo os filhos.
• O BFS pára assim que encontra uma solução, não avaliando mais nenhuma. Assim,
é garantido que encontra a solução mais curta.
• Alterar os pesos das arestas não tem impacto no seu resultado.

Completude: O BFS é considerado completo porque avalia todas as camadas e nós.


Otimização: Tipicamente o BFS não é o mais otimizado, apenas o é quando todas as
ações (arestas) têm o mesmo custo. Esta situação, acaba por transformar o BFS num UCS
(Uniform-Cost search).
Complexidade temporal – Dado que tem de se avaliar todos os nós em cada nível até
chegarmos à solução, acaba por ser bastante demorado.
Complexidade de espaço – O BFS, no pior caso, pode ter todos os nós do nível
correspondente à opção mais curta.

O custo do BFS é o inverso do DFS, porque um é LIFO (DFS) e o outro é FIFO (BFS).
Assim, Cij (DFS) = -Cij (BFS) ou vice-versa

UCS – Uniform Cost Search


• É uma forma de procura que considera sempre o nó com menor custo para
expansão.
• Alterar os pesos das arestas para valores maiores que zero (e não constantes)
influencia o caminho decidido pelo algoritmo.

Completude: Trata-se de um modelo completo. Se existir um estado objetivo (que tem


de ter um tamanho finito), o UCS encontrá-lo-á.
Otimização: É otimizado, se assumirmos que todas as arestas não são negativas. Dado
que se vai procurando o objetivo expandindo os nós de menor custo, é garantido que se
obterá o caminho com menor custo. Ter custos negativos inviabiliza a garantia de
otimização.
Complexidade temporal: Têm de ser avaliados todos os possíveis custos de todas as
ligações.
Complexidade de espaço: Estarão armazenados todos os nós do nível da solução com
menos custo.

Em termos gerais, as três estratégias de procura são similares, variando apenas a forma
de expansão dos nós filhos.

Informed search (pesquisa informada)


A pesquisa não informada é mais completa e otimizada, contudo, pode ter tempos de
execução altos com performances lentas.
Assim, a pesquisa informada permite diminuir tempos de execução através de estimativas
de processamento que evitem processar caminhos menos promissores. Isto pode levar a
uma menor otimização e completude na solução.

Heurísticas – São funções que permitem estimar a proximidade de um dado estado ao


objetivo. Tipicamente recebem como input um estado e como output a estimativa de
distância ao objetivo correspondente. Estas funções normalmente são computadas para
situações específicas e procuram definir a distância mínima para o objetivo. As heurísticas
são soluções para problemas relaxados (relaxed problems) em que são retiradas restrições
dos problemas originais (por exemplo, num jogo de xadrez, permitindo que todas as peças
se movam para qualquer localização sem limites).

Algoritmos de procura informada

Greedy search (pesquisa gulosa)

• É uma estratégia de pesquisa que seleciona sempre o nó com menor valor


heurístico (o algoritmo acredita ser o estado mais próximo do objetivo)
• Usa uma estimativa que avalia se o nó a expandir está próximo do objetivo ou não
• Não tem em conta os custos acumulados por forma a encontrar o caminho de
menor custo

Completude e otimização: O Greedy Search não é garantido que encontre o objetivo


ou, se encontrar, que seja o mais otimizado. Estando dependente das funções heurísticas,
caso estas sejam más, acabará por ser bastante imprevisível em termos de
funcionamento.

A* Search (pesquisa A-Estrela)

• É uma estratégia de pesquisa que procura expandir os nós cujo valor heurístico irá
ter o menor custo para o caminho total até ao objetivo.
• No fundo funciona de forma semelhante ao UCS, em que tem em conta o valor
mais baixo até ao objetivo, mas avalia o caminho através da soma dos valores
heurísticos do caminho.

Completude e otimização: é um modelo ótimo e completo (desde que seja fornecida


uma boa heurística) porque combina as vantagens das restantes estratégias, em particular
da velocidade do greedy search e a otimização e completude do UCS.

Admissibilidade e consistência

O algoritmo de pesquisa A* junta a completude e a otimização do UCS e do Greedy Search


respetivamente. Assim, se:

• g(n) representar o custo computado até ao estado atual;


• h(n) representar o valor heurístico/custo estimado para o próximo ponto;
• f(n) representar o custo total estimado pelo A*

Então: f(n) = g(n) + h(n)

O custo total estimado para um dado estado corresponde ao custo até ao estado
anterior + o custo estimado para o estado pretendido.

Admissibilidade

O critério de admissibilidade define que o custo estimado para alcançar o objetivo através
de heurísticas não deve ser negativo e deve ser sempre inferior ao custo efetivo total para
chegar ao objetivo.

Em termos matemáticos, sendo h(n) o valor estimado e h*(n) o custo efetivo, teremos
a seguinte regra para garantir o critério de admissibilidade:

0 <= h(n) <= h*(n)

Quando a heurística do A* é constante (pode ser visto como h(n)=1, h(n)=2, … em que
todos os caminhos são estimados como tendo o mesmo valor) e não é cumprido o critério
de admissibilidade (não se garante que o custo estimado é positivo e menor ou igual que
o custo total), o A* transforma-se numa lógica BFS porque tem de ser feita a expansão
dos nós camada a camada.

Consistência

Enquanto a admissibilidade verifica se a estimativa total da partida à chegada não


ultrapassa o valor total efetivo, a consistência avalia em cada estado, se a estimativa para
passar ao estado seguinte somada ao custo efetivo tido até chegar ao estado atual, não
ultrapassa o valor total estimado.

No fundo, a admissibilidade valida a estimativa do percurso como um todo enquanto a


consistência avalia a consistência das estimativas na mudança de estado face ao custo já
tido anteriormente.

Exemplos de aplicação do A*:

• Jogos de vídeo
• Movimento de robots
• Reconhecimento de voz
• Traduções automáticas
Dominância

A dominância consiste em avaliar se uma determinada heurística é melhor que outra, ou


seja, se é dominante.

Se as heurísticas do A* forem = 0, então o A* acaba por se tornar o algoritmo UCS, pois


não existem heurísticas para orientar a pesquisa e acabarão por apenas serem tomados
em conta os custos de cada mudança de estado.

Feedforward:

Feedforward é um tipo de rede neural artificial que não possui ciclos ou conexões
recorrentes. Ela processa as informações da camada de entrada para a camada de saída
sem retroalimentação.

Algoritmo de Back-Propagation:

Algoritmo de Back-Propagation é um algoritmo de aprendizagem supervisionada utilizado


para treinar redes neuronais artificiais. Consiste em ajustar os pesos e as polarizações da
rede de modo a minimizar uma função de custo que mede o erro entre a saída desejada
e a saída obtida pela rede.

O algoritmo de Back-Propagation funciona em duas fases:

• Na fase de feedforward, a rede recebe uma entrada e calcula a saída de cada


camada até atingir a saída final. Essa saída é comparada com a saída desejada e o
erro é calculado.
• Na fase de backpropagation, o erro é propagado de volta pela rede, começando
na camada de saída e indo até a camada de entrada. Em cada camada, o erro é
usado para calcular o gradiente da função de custo em relação aos pesos e
polarizações, e esses parâmetros são atualizados usando um método de
otimização, como a descida gradiente.

O algoritmo de Back-Propagation baseia-se na regra da cadeia de cálculo para calcular os


gradientes de forma eficiente. Também requer que as funções de ativação das camadas
sejam diferenciáveis.
Perceptron:

O Perceptron é um modelo básico de rede neural composto por uma única camada de
neurônios, chamada camada de saída.

Cada neurônio recebe entradas ponderadas e aplica uma função de ativação para produzir
uma saída.

O Perceptron é mais utilizado para problemas de classificação binária, onde o objetivo é


separar duas classes de dados por meio de uma linha ou hiperplano.

Ele pode aprender a ajustar os pesos das entradas e o limiar de ativação para melhorar a
precisão da classificação.

O treino do Perceptron segue o algoritmo de aprendizado supervisionado.

Rede Neural Multicamadas (Multilayer Perceptron - MLP):

Uma rede neural multicamadas, é composta por várias camadas de neurônios, incluindo
uma camada de entrada, uma ou mais camadas ocultas e uma camada de saída.

Cada neurônio de uma camada está conectado a todos os neurônios da camada anterior
e da camada seguinte por meio de pesos ajustáveis.

As camadas ocultas são responsáveis por processar as informações intermediárias e


extrair características complexas dos dados de entrada.

A função de ativação é aplicada em cada neurônio para introduzir não-linearidade nas


operações.

O treino de uma rede neural multicamadas geralmente é feito usando algoritmos de


backpropagation, que ajustam os pesos da rede com base na diferença entre as saídas
previstas e as saídas esperadas.

Em suma: O perceptron é utilizado quando se trata de um problema simples e lineares


que não necessitam de uma grande camada de processamento. A rede neural multicamada
é utilizada para funções de mapeamento complexas, grande dimensão de dados e não
lineares em que são ajustadas as camadas ocultas tendo em conta a eficiência e
capacidade de hardware para o processamento. O backpropagation é utilizado para
aprendizagem dos algoritmos através do cálculo do erro, ajustando pesos e custos. O
feedforward não é implementado diretamente, trata-se de uma arquitetura utilizada nas
redes neuronais multicamada para realizar tarefas de classificação e regressão.
Resolução Workflow 1:

1)

A. Estado: representação do ambiente num dado instante


B. Atribuição de desestruturação: consiste na análise de dados presentes nos estados
e na decomposição de estados complexos em estados mais simples de interpretar
e analisar.
C. Árvore de busca: representação em formato de árvore de um algoritmo de procura
em que os nós expandidos vão formando ramos de expansão relativos à pesquisa
efetuada.
D. Nó de busca: Trata-se da representação de um determinado estado.
E. Funções como valores: consiste na utilização de funções diretamente em cálculos
para determinar valores/ações a efetuar.
F. Recuo: trata-se do processo de retroceder na hierarquia de nós expandidos quando
um dado caminho não é bem-sucedido e há a necessidade de procurar noutros
ramos.
G. Função sucessor: Trata-se da função que define qual será o próximo estado/nó que
será expandido
H. Fator de branching: É o fator que identifica a quantidade de ramos que uma árvore
de procura terá.
I. Variáveis estáticas: São as variáveis relacionadas com o ambiente que nunca se
alteram, mesmo com as mudanças de estado.
J. Símbolo inicial: Trata-se do estado inicial do ambiente, antes de qualquer ação
sobre o mesmo.

2) Suponha que ACÇOES-VÁLIDAS (s’) denote o conjunto de ações válidas no estado s, e


que RESULTADO (a, s) denote o estado que resulta da execução de uma ação válida a no
estado s. Considere a função SUCESSOR(s) que produz o conjunto de pares ordenados (a,
s' ) em que cada par define o estado s’ resultante de o agente tomar a ação a no estado
s. Defina a função SUCESSOR em termos das funções ACÇÕES-VÁLIDAS e RESULTADO, e
vice-versa.

SUCESSOR(s) = {(a,s’) | a ∈ ACÕES-VÁLIDAS(s) E s’ = RESULTADO(a,s)}


ACÕES-VÁLIDAS(s) = { a | (a,s’) ∈ SUCESSOR(s)}
RESULTADO(a,s) = { s’ | (a,s’) ∈ SUCESSOR(s)}

Explicação:

a função SUCESSOR devolve um par, em que a é um valor de ações válidas e s’ o estado


resultante dessa ação válida;
A função AÇÕES-VÁLIDAS devolve uma ação válida para um dado estado;
A função RESULTADO devolve o resultado da ação a no estado s

3)

1. Pode haver mais de um programa de agente que implemente uma dada função de
agente? Dê um exemplo ou mostre que não é possível.

2. Existem funções de agente que não podem ser implementadas por qualquer
programa de agente?

3. Dada uma arquitetura de máquina fixa, cada programa de agente implementa


exatamente uma função de agente?

4. Dada uma arquitetura com n bits de armazenamento, quantos programas de


agentes distintos são possíveis nessa arquitetura?

5. Suponha manter fixo o programa de agente, mas aumentamos a velocidade da


máquina por um fator de dois. Isso muda a função de agente?

4) Considere o mundo do aspirador de pó de dois lugares, totalmente observável.

a) Quais dos algoritmos de search desinformada definidos seriam apropriados para


este problema? O algoritmo deveria verificar os estados repetidos?

Resposta: Utilizaria o algoritmo BFS, uma vez que faria uma análise em camada de todos
os pontos para garantir que todo o pó era apanhado. Faria sentido verificar os estados
repetidos para garantir que não voltava a aspirar sítios em que já havia passado.

b) Aplique o algoritmo escolhido para computar uma sequência ótima de ações para
um mundo 3x3 cujo estado inicial tem pó nos três quadrados de cima e o agente
começa no centro.
5) Um espaço de estados finito conduz a uma árvore de busca finita? E no caso de um
espaço de estados finito que é uma árvore? Poderia ser mais preciso em definir que tipos
de espaços de estados levam a árvores de busca finitas?

6) Forneça o estado inicial, o teste de objetivo, a função-sucessor e a função de custo para


cada um dos itens a seguir.

1. Colorir um mapa plano usando apenas quatro cores, de tal modo que não haja duas
regiões adjacentes com a mesma cor.

Resposta:

Estado inicial: nenhuma região do mapa colorida

Teste de objetivo: Todas as regiões pintadas sem nenhuma cor adjacente igual?

Função-sucessor: Gerar uma nova cor para pintar a próxima região. Se cor for igual a
alguma adjacente, gerar nova cor diferente. Caso contrário pintar com cor gerada.

Função de custo: Dado que não existe custo atribuído explicitamente para nenhuma
ação, assume-se o custo de 1. Logo a função de custo total será 1 * o n.º total de ações
efetuadas.

2. Um macaco com um metro de altura está numa sala em que algumas bananas
estão presas no teto, a 2.5 metros de altura. Ele gostaria de alcançar as bananas.
A sala contém duas máquinas empilháveis, móveis e escaláveis, com um metro de
altura cada.

Resposta:

Estado inicial: nenhuma banana apanhada.

Teste de objetivo: Todas as bananas foram apanhadas?

Função sucessor: o macaco consegue apanhar uma banana? Se sim, apanhar a banana
e voltar para o chão. Se não, empilhar máquinas até que a altura das máquinas mais a
dele seja o suficiente para apanhar a banana pretendida.

Função de custo: Dado que não existem custos explícitos no enunciado, assume-se o
custo de cada ação como sendo 1. Logo será 1 * o n.º de ações efetuadas
7) De que modo é que a aplicação de inteligência artificial nas empresas, nomeadamente
nas PME, pode contribuir para a proteção de dados e infraestruturas digitais?

8) Considere um espaço de estados onde o estado inicial é o número 1 e a função-sucessor


para o estado n retorna dois estados, com os números 2n e 2n + 1.

1. Desenho o espaço de estados correspondente aos estados 1 a 15.

Como é que a utilização de uma função heurística pode melhorar a eficiência de busca em
largura (BFS) ou da busca em profundidade (DFS), e qual é o papel da heurística na
tomada de decisões de expansão de nós?

Explicar o que é a heurística

Explicar o que é o BFS e o DFS

Explicar o que é a pesquisa informada

Explicar o que é a pesquisa não informada

Resolução exame modelo

1) Analise como é que a heurística é aplicada na algoritmia para resolver problemas


complexos. Não se esqueça de explicar como uma função heurística pode fornecer
informações úteis durante o processo de busca, ajudando a orientar a seleção de
ações ou caminhos mais promissores [2V]

Resposta:

A heurística é um mecanismo bastante útil na resolução de problemas complexos em


algoritmia. Tratam-se de funções que permitem estimar o custo/distância de um dado
estado até ao objetivo, permitindo que o algoritmo opte por caminhos (ainda que
estimados) que possam ser mais eficientes para alcançar o objetivo final. Desta forma, os
caminhos com uma estimativa de eficiência mais baixos, acabam por ser preteridos em
detrimento daqueles que aparentam ser a melhor forma de resolver um problema,
evitando perda de tempo/recursos de processamento. Ainda assim, é importante garantir
que existe uma boa heurística, garantindo o critério de admissibilidade (que define que a
estimativa de custo do caminho não pode ser superior ao custo efetivo até ao objetivo) e
o critério da consistência (em que os custos das transições de estados são consistentes
quer com a estimativa total feita, quer com o custo efetivo até ao objetivo).

2) Descreva como o algoritmo de busca em profundidade (DFS) funciona e descreva


as situações em que ele é mais adequado do que o algoritmo de busca em largura
(BFS). [2V]

Resposta:

O algoritmo DFS trata-se de um algoritmo de busca não informada cujo mecanismo de


procura é através da análise em profundidade. Trata-se de um algoritmo que funciona
numa lógica LIFO (last in, first out) e que avalia todos os nós até ao último nível de
profundidade e depois vai retrocedendo até regressar ao ponto de poder avaliar o ramo
seguinte. Tem como propósito tentar alcançar o objetivo passando pelo maior número de
nós possíveis.

Por sua vez, o algoritmo BFS, embora também seja um algoritmo de busca não informada,
acaba por ter uma lógica de funcionamento diferente, sendo do tipo FIFO (first in, first
out), efetua uma análise camada a camada, avaliando os nós que se encontram ao mesmo
nível antes de analisar o nível seguinte. Por sua vez, o BFS procura encontrar o caminho
mais curto para um dado objetivo.

No que respeita às situações em que o DFS é mais adequado, pode ser utilizado em
situações cujo objetivo esteja mais profundo na árvore de procura e em que se pretenda
obter um maior número de estados/nós até o alcançar. Ainda assim é necessário ter
cuidado, uma vez que uma quantidade demasiado elevada de níveis podem tornar o DFS
pouco eficiente em termos de tempo devido à profundidade a que terá de ir. Ainda assim,
contrasta com o BFS, em que a sua aplicação é mais adequada para casos em que a
solução se encontra nos níveis mais próximos à origem e o que se pretende é o caminho
mais curto para o objetivo.

3) Explore como a presença de ciclos, a profundidade da árvore de busca e a


distribuição dos nós podem influenciar a eficiência e a eficácia desses algoritmos
dos algoritmos em DFS e BFS? [3V]

Resposta:

Sendo o BFS e o DFS algoritmos de busca não informada, eles não têm conhecimento
relativo à estrutura em que irão atuar. Assim, tanto a presença de ciclos como a
profundidade da árvore de busca e a distribuição dos nós pode influenciar a execução dos
algoritmos.

Relativamente ao DFS, a existência de ciclos provoca que o algoritmo possa eventualmente


nunca terminar. O facto de existirem estados que apontam reciprocamente entre eles,
provoca que a profundidade do ramo de busca nunca termine e faça com que o algoritmo
prossiga por tempo infinito, consumindo todos os recursos disponíveis e acabando por
eventualmente não conseguir dar continuidade à pesquisa, No que respeita à profundidade
de nós, caso existam uma grande quantidade de níveis/camadas, o algoritmo DFS irá
demorar muito tempo. O facto de avaliar todos os nós em profundidade, faz com o tempo
de processamento até chegar ao último nível do ramo seja muito elevado, acabando
também por ocupar bastantes recursos, pois tem de registar em memória todo o caminho
efetuado e todos os nós pelo qual passou para poder recuar e regressar ao ponto em que
avança para o seguinte. Já no que respeita à distribuição dos nós, uma distribuição
equivalente dos mesmos acaba por não ser vantajoso para a execução do DFS, uma vez
que existem diversas possibilidades de soluções, fazendo com que o DFS não consiga dar
a solução ótima.

Já quanto ao BFS, é menos propenso à criação de loops de execução quando existem


ciclos, uma vez que a pesquisa é feita camada a camada e assim que o objetivo for
alcançado a pesquisa termina. Ainda assim, podem sempre acontecer. No que respeita à
profundidade dos nós, o BFS não é o mais adequado para pesquisas neste âmbito, uma
vez que a pesquisa é feita em camadas e são analisados todos os nós em cada camada
antes de avançar para o seguinte, sendo o BFS menos vantajoso face ao DFS nesta
situação. Por fim, quanto à distribuição dos nós, o BFS é mais eficiente nos casos em que
os nós estão menos distribuídos, avaliando os vários níveis e parando a execução quando
o objetivo é alcançado. Assim, é garantido que o BFS chega sempre a uma solução (quando
existe) e esta é sempre a mais curta.

4) Analise como a arquitetura de uma rede neural pode ser projetada para realizar
tarefas de classificação ou regressão? Quais são os componentes essenciais da rede
neural nesse contexto [3V]

Resposta:

5) Qual é a diferença entre um Perceptron e uma rede neural multicamadas? Explique


as características e o funcionamento de cada um desses modelos? [3V]
Resposta:

Um perceptron é um modelo básico de rede neural composta por apenas um neurónio


artificial. Permite o processamento de conjuntos de dados simples e lineares e o seu
processamento não consome muitos recursos. Em termos de funcionamento, recebe um
(ou mais) valores de entrada, aplica funções de ativação e devolve uma saída. Este tipo
de neurónio artificial é comum para análise de problemas binários.

Já uma rede neuronal multicamada consiste na interligação de várias camadas de


neurónios. São adequadas a processamento de informação complexa, como regressão e
classificação, contudo o seu processamento requer mais capacidade de hardware e,
consoante o problema, pode também ser mais demorado em termos de duração. É
composta por uma camada de entrada, múltiplas camadas ocultas (que podem variar em
função da complexidade do processamento a efetuar) e uma camada de saída. No seu
funcionamento, a camada de entrada recebe os valores de entrada, efetua o
processamento, encaminha para as camadas ocultas (que o processam e encaminham
tantas vezes quantas camadas ocultas existirem) até que chega à camada de saída e é
devolvido. Uma rede multicamada também pode ser denominada de rede
“multiperceptron”, pois cada camada oculta funciona como um perceptron, estando vários
interligados.

6) Como é que a utilização de heurísticas influencia o desempenho e a qualidade das


soluções encontradas por algoritmos de otimização? Explique como a escolha e o
ajuste adequado de uma heurística podem ajudar a melhorar a convergência e a
qualidade das soluções obtidas em problemas de otimização [3V]

Resposta:

A utilização de heurísticas pode influenciar de forma bastante impactante o desempenho


e a qualidade das soluções encontradas pelos algoritmos de otimização.

As heurísticas são funções que permitem estimar o custo de determinada ação ou caminho
pode envolver em termos de processamento. Assim, uma boa heurística pode fazer com
que o algoritmo consiga de forma rápida e eficiente optar por ramos de busca que possam
ser mais promissores na obtenção do objetivo que outros. Contudo, é importante que a
heurística seja de qualidade e esteja adequada. Para isso, contribuem os critérios de
admissibilidade e consistência.

A admissibilidade trata-se do critério que define que o custo estimado de um determinado


caminho é igual ou inferior ao custo efetivo desse caminho. Isto permite garantir que o
percurso a ser utilizado e utilizado não é superior àquele que existirá efetivamente. Como
complemento à admissibilidade existe a consistência. A consistência tem como propósito
avaliar se a estimativa de custo da mudança de estado é consistente e coerente com a
estimativa total efetuada e com o custo total efetivo do caminho. Para além destes dois
conceitos, existe ainda um terceiro que é importante para garantir uma boa heurística: a
dominância. Deverá garantir-se que através das heurísticas definidas, existirá a
dominância de uma solução em relação às restantes, sendo esta a solução ótima.

Garantindo uma boa heurística, os algoritmos de procura acabam por tirar diversos
proveitos na fase de processamento e de procura. O facto de serem otimizadas as escolhas
relativamente à procura em ramos que parecem ser mais promissores que outros, acaba
por trazer benefícios no tempo de procura, pois não se faz uma procura cega, mas sim
guiada em estimativas de custo. Também ao nível dos recursos acaba por ser mais
eficiente, pois pode poupar-se memória no armazenamento de quantidades de estados
que podem nem sequer ser relevantes para a resolução do problema pretendido.

7) Quais são os principais desafios de projetar uma heurística eficiente? Discuta os


trade-offs entre precisão e eficiência computacional ao desenvolver uma função
heurística para problemas de grande escala [4V]

Resposta:

A criação de funções heurísticas eficientes permitem aos algoritmos serem capazes de


responder melhor aos problemas para os quais são desenhados. Ainda assim, para que
sejam eficientes, a sua projeção enfrenta uma série de desafios.

O desenvolvimento de funções heurísticas eficientes e adequadas começa com uma


interpretação clara do problema, através da identificação dos pontos chave e da
clarificação de eventuais pontos problemáticos na codificação dos algoritmos. Também
muito relevante, a contextualização do problema é algo que permite tomar decisões
durante o desenvolvimento das funções. Esta contextualização permite identificar
características próprias do que se pretende alcançar e, desta forma influenciar a
implementação.

De seguida, deve-se identificar o tipo de algoritmo a aplicar à situação em concreto e,


tipicamente, existem diversas formas de abordar a resolução de um problema, cada um
com as suas vantagens e desvantagens.

É necessário então desenvolver uma função heurística adequada. Deverá ser feito um
equilíbrio entre a exploração de novas informações e a utilização de informações já
conhecidas para melhorar a sua resposta. O não equilíbrio pode levar a tempos elevados
de procura ou a soluções não ótimas devido à não exploração de informação adicional para
além da conhecida.

Após a implementação das primeiras versões das funções heurísticas, é necessário treiná-
las para que possam familiarizar-se e otimizar-se em termos de processamento da
informação. A utilização de um conjunto de dados alargado e variado permitirá às funções
heurísticas serem capazes de otimizar a sua capacidade de resposta. Isto servirá também
para avaliar e validar a capacidade de resposta das funções.

Contudo, durante o desenvolvimento, é necessário ter em conta alguns trade-offs para o


desenvolvimento. A avaliação da necessidade de precisão face à necessidade de um tempo
de execução baixos influenciam a implementação a efetuar.

Em situações em que a precisão da resposta pode ser algo crucial para o desenvolvimento
de uma tarefa, deve-se admitir um tempo de processamento computacional mais elevado,
que permita às funções aprimorar e avaliar de forma mais detalhada e cuidada o resultado
a devolver. No caso de situações em que a precisão não necessita de ser efetivamente
pormenorizada, pode ser diminuído o tempo de processamento em detrimento da
precisão. Para este trade-off, pode também ser relevante o hardware disponível e os
recursos financeiros envolvidos, uma vez que tanto a precisão como o tempo de
processamento podem ser melhorados caso equipamento como memórias, processador,
discos rígidos, entre outros, sejam mais potentes. Ainda assim, os recursos são finitos e é
necessário avaliar o que é efetivamente relevante no contexto do problema, não
esquecendo de que toda a escrita das funções deve ser o mais otimizada possível,
prevendo a avaliação de grandes volumes de dados e mantendo a capacidade de ser
escalável.

Exame 14:00

1) Quais são as vantagens e desvantagens da implementação do algoritmo de procura


em profundidade limitado em comparação com a implementação do algoritmo de
profundidade ilimitada?

Resposta:

O algoritmo de procura em profundidade trata-se de um algoritmo de busca não


informada, ou seja, é executado sobre um ambiente no qual não tem conhecimento do
ambiente em que está inserido e não sabe onde se encontra o objetivo.

<Explicação DFS> + tem a limitação de poder entrar em loops ou de ser muito demorado
quando existem muitos níveis de profundidade para avaliação conjunto de dados é infinito,
aumentando os recursos consumidos e o tempo de execução. Assim, a busca em
profundidade limitada trata-se de uma implementação do DFS em que é imposta uma
limitação no número de níveis de profundidade a que o algoritmo de busca pode chegar.
Tem as vantagens de diminuir o tempo de processamento, de necessitar de menos
recursos computacionais e de não entrar em loop em caso de árvores de busca infinitas.
Contudo, apresenta como desvantagens a possibilidade de não encontrar nenhum
resultado mesmo que este exista, de não apresentar o resultado com o maior número de
nós possível e de não ser completo, uma vez que com a limitação imposta pode não
processar todas as hipóteses possíveis.

2) Descreva o algoritmo A* (A-Star) e explique como ele implementa a search


heuristica e a search em largura.

Resposta:

O algoritmo A* trata-se de um algoritmo de procura informada, ou seja, tem conhecimento


sobre o ambiente em que está inserido e onde se encontra a localização do objetivo.

Este algoritmo é considerado ótimo e eficiente, uma vez que combina a análise do custo
com o tempo de execução, tudo isto devido à utilização de heurísticas e do modo de
funcionamento do BFS. O A* atua sobre a camada em que se encontra, aplicando uma
função heurística a cada nó desse nível por forma a decidir qual o nó seguinte que irá
expandir. O nó a expandir será aquele cujo custo estimado somado ao custo efetivo do
caminho já percorrido até ao estado atual seja o menor possível. Esta análise ocorre
camada a camada conforme o comportamento do BFS, utilizando a heurística para otimizar
o caminho a percorrer, deixando de lado nós que aparentem ser menos relevantes e menos
propícios a levar ao objetivo.

Para que este comportamento funcione, é necessário que a heurística seja boa, ou seja,
tem de ser admissível (o custo total estimado tem de ser maior que zero e não pode ser
superior ao custo efetivo do caminho até ao objetivo), tem de ser consistente (o custo de
mudança de estado somado ao custo total do caminho tem de ser consistente com o valor
total efetivo) e tem de haver uma dominância (uma solução tem de prevalecer sobre as
restantes).

3) Explique o conceito de rede neural e como pode ser implementada por uma função
de avaliação (Heuristica) para melhorar o desempenho de algoritmo de busca como
o "Uniform Cost Search"?
Resposta:

Rede neural consiste num modelo computacional que tem como intuito simular o cérebro
humano. Trata-se de um conjunto de camadas a que se dá o nome de neurónios que
funcionam como mecanismos de processamento de informação. Normalmente, existe uma
camada de entrada, camadas de processamento (ou camadas ocultas) e uma camada de
saída. As camadas de processamento são denominadas de neurónios e estão interligadas
entre si. Processam os dados de entrada e geram outputs que são enviados para os
neurónios interligados. Cada neurónio tem um peso na rede neural que significa a sua
relevância para o resultado final. Tal como no cérebro humano, estas redes neurais
necessitam de treino, que permite otimizar a capacidade de processamento e os resultados
obtidos, existindo para isso funções de custo (que avaliam o resultado obtido face ao
resultado efetivo) e mecanismos de back propagation, que permitem ajustar os pesos de
cada neurónio e o seu impacto na rede.

A utilização de funções de heurística no UCS permitem estimar o custo total até ao


objetivo e organizar os nós a expandir em ordem crescente, permitindo ao algoritmo focar-
se nos nós que aparentam ter um custo de expansão mais baixo e ótimo. Assim, o
algoritmo pode focar-se nos resultados que parecem mais promissores e ser mais rápido
e eficiente na sua execução.

4) Analise como a escolha adequada da função de agente e do programa de agente


pode criar impacto no desempenho e no comportamento de um agente artificial.

Resposta:

É importante adequar a função de agente e o programa de agente por forma a otimizar o


impacto e o desempenho de um agente artificial.

Um agente artificial consiste numa entidade que irá impactar o ambiente em que está
inserido de alguma forma. O seu impacto é definido através da função do agente, no qual
está definido o impacto que agente irá ter e a forma como o irá ter. Contudo, para agir, o
agente e a função de agente devem estar incluídas num programa de agente. Este
programa de agente é responsável por interpretar os inputs recebidos do ambiente,
processá-los e identificar qual a ação a efetuar. Com base nesse processamento, dá
indicação ao agente, fazendo com que este atue de acordo com a sua função.

Adequar a função do agente ao programa de agente permite harmonizar os inputs


recebidos e os outputs fornecidos. Uma definição clara da função do agente aliada a um
programa de agente adequado permitem diminuir o tempo de processamento dos inputs
até gerar outputs, aumentar a capacidade de resposta do agente e torna-lo mais
responsivo e capaz de aprender e evoluir com os novos inputs que vão sendo dados. O
direcionamento do programa de agente à função que se pretende também pode ser
bastante importante, pois pode permitir ao agente focar-se em determinada ação em lugar
de ainda ter de avaliar ações que podem não interessar para o caso. Isto permite diminuir
o tempo de resposta.

5) Como a utilização de uma função heurística pode melhorar a eficiência de uma


busca em largura (BFS) ou da busca em profundidade (DFS) e qual o papel da
heurística na tomada de decisões de expansão de nós?

Resposta:

Tanto o BFS como o DFS são algoritmos de busca não informada, ou seja, não têm
conhecimento do ambiente em que estão inseridos nem a localização do objetivo. Ambos
efetuam a sua procura através da avaliação de nós de forma cega, ou seja, sem avaliação
de custos ou pesos. No caso do DFS, trata-se de uma verificação em profundidade,
utilizando uma lógica LIFO (last in, first out) em que o são explorados os ramos da árvore
de busca na procura do caminho até ao objetivo que consiga expandir o maior número de
nós possível. Por sua vez, o BFS tem um funcionamento diferente, organizando os nós em
FIFO (first in, first out), ele faz uma avaliação dos nós camada a camada, sendo certo que
encontra uma solução no caso desta existir e que esta é a mais curta. Em termos de
eficiência e otimização, nenhum dos dois é eficiente nem ótimo, uma vez que não olham
a custos e os seus tempos de execução podem ser bastante demorados consoante o
número de ramos e a densidade de nós existente. Excecionalmente, o BFS pode ser ótimo
nos casos em que os custos de expansão são constantes, iguais e não negativos.

A heurística assume um papel importante na otimização dos algoritmos de busca. Sendo


usada em algoritmos informados (como o A* ou o Greedy Search), as funções heurísticas
permitem estimar custos de expansão de nós que permitem ao algoritmo focar-se na
procura de caminhos que aparentem ser mais promissores. Esta estratégia permite reduzir
o tempo de execução e os recursos consumidos, uma vez que existe uma definição do
caminho a seguir e que poderá garantir uma solução ótima.

A aplicação de heurísticas ao BFS e DFS pode assumir um papel importante na otimização


dos algoritmos, uma vez que permite ordenar os nós a expandir de forma a que o algoritmo
se possa focar naqueles que, conforme os valores heurísticos estimados, podem estar mais
perto da solução ótima. Desta forma, os algoritmos podem deixar os caminhos menos
interessantes e com menos probabilidade de sucesso de lado.

6) Em que situações a aplicação de uma heurística é mais vantajosa? durante a busca


em largura ou durante a busca em profundidade? Explique as vantagens e
desvantagens de usar uma heurística em cada uma destas estratégias.

Resposta:

A utilização de heurística é mais vantajosa na busca em largura (BFS), devido à sua forma
de funcionamento, uma vez que a procura ocorre camada a camada, a utilização de uma
função heurística que consiga ordenar os nós em cada camada para que seja expandido
aquele que aparente ser ótimo em lugar de avaliar todos os nós da camada sem qualquer
organização particular. No DFS, a utilização de heurísticas acaba por não ser tão benéfico,
uma vez que a aplicação de heurísticas iria definir a ordem com que os ramos seriam
expandidos em profundidade, mas o número de níveis poderia ser tão elevado que
acabaria por demorar demasiado tempo e o ganho da função heurística não seria
relevante.

Em termos de desvantagens, a aplicação de uma heurística que não seja de qualidade ao


BFS e ao DFS poderá levar à escolha de soluções que não são ótimas e aumentar de forma
elevada o tempo de execução do algoritmo, podendo no caso do DFS estragar qualquer
otimização que se tente efetuar pois pode levar o algoritmo por caminhos demasiado
profundos e que consumam demasiado tempo e recursos para recuar e expandir um novo
ramo.

Ainda assim, em termos gerais, com a utilização de heurísticas adequadas, admissíveis,


consistentes e dominantes, existem diversas vantagens na utilização de heurística nestes
dois algoritmos. No BFS permite reduzir o tempo de execução, minimizar os recursos
consumidos, através da diminuição de nós expandidos, permitindo chegar a uma solução
ótima em menos passos e tempo. Já no DFS, torna-se bastante eficaz quando o estado
objetivo se encontra num nível próximo ao de partida, permitindo ao algoritmo poupar
tempo de execução.
7) Suponha que quer encontrar o caminho mais curto entre a entrada e saída de um
labirinto.
a. Admitindo que não dispõe de nenhuma informação a não ser os movimentos
possíveis a partir do nó corrente, que método de procura utilizaria?

Resposta:

Assumindo que não existe qualquer informação relativamente ao labirinto, o tipo de


algoritmo mais adequado será um algoritmo de busca não informada, ou seja, que
funciona sem conhecimento do meio envolvente nem conhecimento da localização do
objetivo. Dentro desse tipo, e considerando que existe a informação dos movimentos
possíveis a partir do nó corrente, utilizaria o algoritmo BFS. Este algoritmo permitiria
avaliar em cada camada (ou seja, em cada posição) as diferentes ações que poderiam ser
tomadas (os movimentos possíveis) para validar se já estava na saída, garantindo que se
obtém o caminho mais curto possível até à saída.

b. Conhecendo as localizações da entrada e da saída, será possível definir alguma


heurística? Se sim, que método de procura utilizaria?

Resposta:

Havendo informação da entrada e saída, poderia passar-se a usar um algoritmo de procura


do tipo informado. Logo, a partir daí seria possível definir heurísticas que permitissem
procurar o caminho até à saída.

Para este caso, utilizaria o algoritmo A*, uma vez que utilizaria heurística para juntar à
distância já percorrida ao valor estimado de proximidade ao destino do próximo nó a
expandir.

Você também pode gostar