<?xml version="1.0" encoding="UTF-8"?><!-- generator="wordpress.com" -->
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	>

<channel>
	<title>inteligencia-artificial &amp;laquo; WordPress.com Tag Feed</title>
	<link>http://wordpress.com/tag/inteligencia-artificial/</link>
	<description>Feed of posts on WordPress.com tagged "inteligencia-artificial"</description>
	<pubDate>Sat, 26 Jul 2008 14:47:40 +0000</pubDate>

	<generator>http://wordpress.com/tags/</generator>
	<language>en</language>

<item>
<title><![CDATA[Códigos Ativação]]></title>
<link>http://aifuture.wordpress.com/?p=37</link>
<pubDate>Fri, 25 Jul 2008 20:54:18 +0000</pubDate>
<dc:creator>edersonmelo</dc:creator>
<guid>http://aifuture.wordpress.com/?p=37</guid>
<description><![CDATA[Sempre vale recordar. Ainda mais que muitas das grandes idéias podem nascer de filmes que são cons]]></description>
<content:encoded><![CDATA[<p>Sempre vale recordar. Ainda mais que muitas das grandes idéias podem nascer de filmes que são considerados ficção científica. Como as portas de shoppings que abrem sozinhas. Mostradas anos antes de serem criadas nos filmes <a href="http://www.google.com.br/url?sa=t&#38;ct=res&#38;cd=1&#38;url=http%3A%2F%2Fwww.startrek.com%2F&#38;ei=JDqKSITeF5XmvQW9zK2uDg&#38;usg=AFQjCNH2F9N4xMmpAWwMvsvfHVv6mBXrag&#38;sig2=iYbdum3KGoDzQhYD6BgNpg" target="_blank">Star Trek</a>.</p>
<p>O filme <strong>A.I</strong>. mostra uma idéia de ativação de <strong>David </strong>que é fantástica. Ele é ativado por um toque na nuca, com o soletrar de palavras. Isso ativa David e o torna "humano". Desta forma David passaria a ter comportamento de uma criança(humana), sendo impossível a desativação comportamental. Para isto ocorrer, ele deveria ser destruido.</p>
<p style="text-align:center;"><span style='text-align:center; display: block;'><object width='425' height='350'><param name='movie' value='http://www.youtube.com/v/qdFuv3tnZh4'></param><param name='wmode' value='transparent'></param><embed src='http://www.youtube.com/v/qdFuv3tnZh4&rel=0' type='application/x-shockwave-flash' wmode='transparent' width='425' height='350'></embed></object></span></p>
<blockquote><p><strong>Mais sobre o filme:</strong></p>
<p>A.I. é como um conto de fadas. Comovente. Passa-se numa época em que os robôs fazem parte do cotidiano dos homens. Eles prestam serviços, mas também podem substituir um parente que faleceu ou até mesmo um amante. Até que é criado um menino robô programado para amar.</p>
<p>David é adotado por Henry e Mônica . Ele vai substituir o filho do casal, portador de uma doença terminal, que está congelado à espera de descoberta da cura.</p>
<p>O robô David passa a viver com o casal e vai se adaptando. Porém, o filho orga (de orgânico, como são chamados) fica curado e volta para casa. O filho meca (de mecânico) perde espaço. E passa a se comportar como um humano real. Disputa o amor da mãe.<br />
A convivência não se torna  pacífica dos dois garotos, então David  é levado para a floresta, acreditando que ele pode sobreviver ali. Não podendo  devolver à empresa que o criou, pois ele seria destruído.</p>
<p>Mais um detalhe muito bom é o ursinho Teddy. Ele é encantador, apaixonante. Na verdade, é uma combinação de boneco com imagem digital e foram usados vários Teddies. O mais importante deles continha 50 motores em seu corpo, 24 deles só na cabeça, controlando seus complexos movimentos de rosto. Teddy pesava mais de 13 quilos.</p></blockquote>
<p><em>Abraço,<br />
Ederson Melo</em></p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[Redes neurais permitem que robôs sintam empatia]]></title>
<link>http://intartificial.wordpress.com/?p=121</link>
<pubDate>Thu, 24 Jul 2008 15:07:49 +0000</pubDate>
<dc:creator>STRØNGM@N</dc:creator>
<guid>http://intartificial.wordpress.com/?p=121</guid>
<description><![CDATA[
Com a ajuda de redes neurais, pesquisadores europeus estão desenvolvendo robôs que poderão senti]]></description>
<content:encoded><![CDATA[<p><a href="http://intartificial.files.wordpress.com/2008/07/robo_empatia.jpg"><img src="http://intartificial.wordpress.com/files/2008/07/robo_empatia.jpg?w=238" alt="" width="238" height="156" class="alignnone size-medium wp-image-122" /></a></p>
<p>Com a ajuda de redes neurais, pesquisadores europeus estão desenvolvendo robôs que poderão sentir empatia, sintonizando-se com as emoções dos humanos com quem eles interagirem e reagindo de acordo com essas emoções.</p>
<p>Detectando emoções</p>
<p>Utilizando câmeras digitais e sensores, os robôs conseguem detectar diferentes parâmetros, como as expressões faciais, o tom de voz e a proximidade das pessoas ao seu redor. Seu programa de controle utiliza esses parâmetros para detectar quando a pessoa está zangada, feliz ou triste.</p>
<p>Tal como uma criança, os robôs conseguem aprender a partir da observação das emoções. Eles já conseguem, por exemplo, distinguir entre os sentimentos de uma pessoa que chora de tristeza daqueles de outra pessoa que chora de alegria.</p>
<p>Adaptando o comportamento</p>
<p>Essas informações já utilizadas para que o robô adapte seu comportamento e até sua aparência para contrabalançar a emoção demonstrada pela pessoa. Ele pode, por exemplo, mudar seu comportamento para parecer menos ameaçador, e até mesmo se retirar do local, se necessário.</p>
<p>O objetivo do projeto, que envolve 25 especialistas de seis países europeus, é fazer com que os robôs tenham empatia, ajustando-se às emoções humanas, o que poderá facilitar sua aceitação no dia-a-dia das pessoas.</p>
<p>Robôs simples de comportamento complexo</p>
<p>Os robôs propriamente ditos são muito simples, disponíveis no mercado ou construídos pelos pesquisadores com peças que se pode comprar no comércio.</p>
<p>Mas a sua inteligência reúne técnicas de sistemas adaptativos, psicologia comparativa e desenvolvimental, neurociências e etologia - enfim, todas as ferramentas que os cientistas dispõem para estudar o comportamento humano.</p>
<p>Fonte: <a href="http://www.inovacaotecnologica.com.br/noticias/noticia.php?artigo=redes-neurais-permitem-que-robos-sintam-empatia&#38;id=010180080723">Inovação Tecnológica</a></p>
<p>See ya!!!</p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[Nem toda AI é do mal...]]></title>
<link>http://aifuture.wordpress.com/?p=34</link>
<pubDate>Wed, 23 Jul 2008 17:15:27 +0000</pubDate>
<dc:creator>edersonmelo</dc:creator>
<guid>http://aifuture.wordpress.com/?p=34</guid>
<description><![CDATA[Tenho notado em algumas discussões(leves claro), que muitas pessoas tem um certo medo, quanto a Int]]></description>
<content:encoded><![CDATA[<p>Tenho notado em algumas discussões(leves claro), que muitas pessoas tem um certo medo, quanto a <strong>Inteligência Artificial(AI).</strong> Na maioria das vezes, as pessoas pensam em dominação total por parte de alguma AI, na extinção da Raça Humana. Também tem muita gente com medo do desemprego, da falta de utilidade para nós, etc.</p>
<p>Não vou negar que alguns desses medos eu tenha. Mas mesmo com as pesquisas atuais com <strong>Redes Neurais</strong>, seria quase impossível uma extinção.</p>
<p>Mas continuamos as discussões tradicionais como não deixaria de ser.<br />
Mas temos bons(acho) exemplos da utilização de AI como a declaração de <a href="http://www.google.com/corporate/execs.html" target="_blank"><strong>Larry Page</strong></a> no começo do ano:</p>
<blockquote><p>O <a href="http://www.google.com.br" target="_blank">Google </a>está trabalhando para criar inteligência artificial.<br />
“Não é tão complicado como parece”, disse o co-fundador do Google.</p></blockquote>
[caption id="attachment_35" align="aligncenter" width="300" caption="google bem, google mal"]<a href="http://aifuture.wordpress.com/files/2008/07/google.jpg"><img class="size-medium wp-image-35" src="http://aifuture.wordpress.com/files/2008/07/google.jpg?w=300" alt="google bem, google mal" width="300" height="203" /></a>[/caption]
<p>O sistema de hierarquização do que é produzido e publicado na web pelo Google já cria em si uma forma de inteligência.</p>
<p>O Google traduz necessidades do pensamento coletivo e "desejos" dos seus usuários. O mesmo tipo de processo é utilizado pela Google para as demais ferramentas: <a href="http://gmail.com" target="_blank">gmail </a>por exemplo.</p>
<p>Sobre o livro!? Ainda mal comecei, falta de tempo mesmo. Diferente de uma máquina, eu preciso dormir.</p>
<p><em>Abraço,<br />
Ederson Melo</em></p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[Los videojuegos son cada vez más realistas y menos predecibles]]></title>
<link>http://sabesqsi.wordpress.com/?p=144</link>
<pubDate>Mon, 21 Jul 2008 22:13:43 +0000</pubDate>
<dc:creator>chaban</dc:creator>
<guid>http://sabesqsi.wordpress.com/?p=144</guid>
<description><![CDATA[Por Gonzalo Mengarelli
Esta noticia no hace mas que confirmar el avance tecnológico en cuantos a gr]]></description>
<content:encoded><![CDATA[<p style="text-align:left;">Por <strong>Gonzalo Mengarelli</strong><img class="aligncenter" src="http://infobae.com/adjuntos/imagenes/93/0219336G.jpg" alt="" width="305" height="170" /></p>
<div id="texto2" class="Georgia t16 c000000 tdn pb5">Esta noticia no hace mas que confirmar el avance tecnológico en cuantos a gráficos pero tal vez el retroceso en las tramas, ya que varios juegos pierden originalidad en este sentido.</div>
<div class="Georgia t16 c000000 tdn pb5"></div>
<div class="Georgia t16 c000000 tdn pb5">Comenzarán a emplear la <strong>inteligencia artificial</strong>, lo cual hará que los enemigos sean más organizados una vez que el usuario vaya tomando decisiones</div>
<div id="texto" class="georgia t16 c000000 tdn pb5 pt5">Así surge de las presentaciones realizadas en la feria E3, la más importante de la industria.</p>
<p>"Teníamos que hacer mucho" para mejorar, explicó Peter Hines, de la compañía Bethesda Softworks, que presentó su juego <em>Fallout 3</em>, que introduce un personaje en el Washington posnuclear.</p>
<p>La introducción de la inteligencia artificial en este videogame permite a los enemigos cambiar de tácticas a medida que el usuario toma una u otra decisión. Asimismo, <em>Fallout 3</em> permite que las elecciones de los jugadores transformen a los rivales en aliados o enemigos.</p>
<p><em>Project Origin</em>, de Monolith Productions para Warner Interactive Studios, pone el acento en el realismo de las acciones del enemigo y la utilización del entorno para lograr ventaja.</p>
<p>Por su parte, Sony Online Entertainment está terminando <em>The Agency</em>, videogame que le permite a los jugadores disponer de espías las 24 horas en internet. Si estos espías necesitan ayuda, pueden enviar al jefe correos electrónicos o mensajes SMS, explicó Matt Wilson, uno de los responsables del juego, indica la agencia de noticias <em>AFP</em>.</p>
<p>"Puedes enviar un espía para encontrar a un capo de la droga colombiana, que va a encontrarse enseguida sentado en un bar enviándonos un mensaje diciendo que encontró su objetivo", agregó.</p>
<p>"La mala noticia es que ha sido capturado, y que sus captores amenazan con matarlo si no pagamos un millon de dólares. Tienes que pulsar 1 en el teléfono para pagar el rescate, o 2 para negarte a pagarlo", concluyó.</p></div>
]]></content:encoded>
</item>
<item>
<title><![CDATA[Filme de 1997 mostra AI alterada por vírus]]></title>
<link>http://aifuture.wordpress.com/?p=31</link>
<pubDate>Mon, 21 Jul 2008 11:55:50 +0000</pubDate>
<dc:creator>edersonmelo</dc:creator>
<guid>http://aifuture.wordpress.com/?p=31</guid>
<description><![CDATA[Assistindo tv num domingo sem canal fechado é muito cruel. Mais cruel ainda é sem um computador po]]></description>
<content:encoded><![CDATA[<p>Assistindo tv num domingo sem canal fechado é muito cruel. Mais cruel ainda é sem um computador por perto. Eis que passando pelo canal da ulbra tv, estava dando um filme que assisti a 10 anos, <a href="http://www.imdb.com/title/tt0119794/" target="_blank">N.I.R.V.A.N.A.</a></p>
<blockquote><p>O roteiro conta a história de Jimi, um <a href="http://pt.wikipedia.org/wiki/Designer_de_jogos" target="_blank">designer de games</a> de sucesso que descobre que um vírus deu vida a Solo, personagem principal de seu jogo. A partir daí, Jimi busca ajuda para deletar seu jogo antes que ele seja lançado e para encontrar sua namorada Lisa.</p></blockquote>
<p>Neste <a href="http://www.imdb.com/title/tt0119794/" target="_blank">filme </a>o personagem virtual, preso dentro de um jogo eletrônico, se encontra num "laço no tempo". Cada vez que é morto no jogo, ele volta ao começo mas sempre com a memória do que ocorreu antes.</p>
<p>O <a href="http://www.imdb.com/title/tt0119794/" target="_blank">filme </a>mostrar idéias ultrapassadas, mas a forma de uma inteligência artificial criada para o jogo se torna viva apartir de um vírus é muito interessante e a única do filme.</p>
<p>E AINDA LENDO O LIVRO.</p>
<p><em>Abraço,<br />
Ederson Melo</em></p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[Algoritmos Genéticos - Parte 4]]></title>
<link>http://sofiaia.wordpress.com/?p=28</link>
<pubDate>Thu, 17 Jul 2008 02:28:30 +0000</pubDate>
<dc:creator>vinigodoy</dc:creator>
<guid>http://sofiaia.wordpress.com/?p=28</guid>
<description><![CDATA[Hoje me reuni com a equipe que está desenvolvendo um algoritmo genético para identificação de pl]]></description>
<content:encoded><![CDATA[<p>Hoje me reuni com a equipe que está desenvolvendo um algoritmo genético para identificação de placas. Participou da reunião o prof. dr. Roberto Raittz, com grande experiência no assunto. Entre as discussões, falamos sobre os algoritmos de seleção e o professor mostrou um algoritmo muito interessante, que ele mesmo desenvolveu.</p>
<p>Procurei na Internet sobre o algoritmo e não encontrei. Então, chamei-o de RaittzSelection e adicionei ao SofiaIA. Os passos para o algoritmo são os seguintes:</p>
<ol>
<li>Escolha um número aleatório no intervalo [0 e 1);</li>
<li>Eleve esse número por uma constate dada, normalmente entre 0,8 e 1,2. Note que, por ser um número menor que zero, uma constante maior que um tenderá a resultados pequenos, mais próximos ao zero, enquanto uma constante menor que um tenderá a resultados próximos de 1.</li>
<li>Multiplique esse resultado pelo tamanho da população. O resultado obtido será o índice do elemento a ser selecionado. A população deve estar ordenada em ordem decrescente.</li>
</ol>
<p>Simples não? Abaixo, a implementação do algoritmo em C++:</p>
<p>[sourcecode language="cpp"]<br />
template <typename Individual><br />
class RaittzSelection : public SelectionFunction<Individual><br />
{<br />
   private:<br />
      private double exponent;<br />
      sofia::util::Random random;</p>
<p>   public:<br />
      explicit RaittzSelection(double _exponent = 1.1)<br />
         : exponent(_exponent) {}<br />
      explicit TournamentSelection(double _exponent = 1.1, unsigned seed)<br />
         : exponent(_exponent), random(seed) {}</p>
<p>      virtual ScoredPopulation select(const ScoredPopulation& population, int amount)<br />
      {<br />
        ScoredPopulation selected = new ScoredPopulation();</p>
<p>        for (int i = 0; i < amount; i++)<br />
        {<br />
           //Generate a number from 0 to size()-1<br />
           int index = static_cast<int>(population.size() *<br />
              pow(random.nextDouble(), exponent));<br />
           selected.push_back(population[index];<br />
        }<br />
        return selected;</p>
<p>      }<br />
}; [/sourcecode]</p>
<p>O algoritmo ainda tem algumas propriedades interessantes. A escolha do índice permite-nos definir o quão elitista o algoritmo será. Quanto mais alto, maior o elitismo. Um índice exatamente igual a 1 torna ele totalmente aleatório.</p>
<p>Um índice grande demais é também problemático. Um índice de 2, por exemplo, pode levar a Convergência Prematura, já discutida. Um índice pequeno demais pode levar a estagnação. O professor recomenda índices os índices entre 1,1 e 1,2.</p>
<p>Para demonstrar melhor esse comportamento, considere o seguinte gráfico que mostra a relação entre o valor sorteado e o expoente. O ponto plotado nada mais é do que o valor sorteado elevado ao expoente.</p>
[caption id="attachment_36" align="alignright" width="675" caption="Seleção de Raiitz"]<a href="http://sofiaia.wordpress.com/files/2008/07/raittzselection.png"><img class="size-full wp-image-36" src="http://sofiaia.wordpress.com/files/2008/07/raittzselection.png" alt="Seleção de Raiitz" width="675" height="423" /></a>[/caption]
<p>Podemos observar claramente que expoentes menores que 1 tenderão a resultados próximos 1, portanto, a selecionar elementos próximos do final da lista, de baixo score. Já os expoentes maiores que 1, por outro lado, obtém resultados próximos de 0, que representam indivíduos do início da lista, ou seja, na elite.</p>
<p>Agora, observe que para o expoente 1, os resultados distribuem-se linearmente. Afinal, o número sorteado elevado a 1 não se alterará. Isso quer dizer que, desde que o gerador de números aleatórios tenha uma distribuição uniforme (que é o caso da SofiaIA), todos os indivíduos terão a mesma chance de serem escolhidos.</p>
<p>Outra grande vantagem do algoritmo é que ele dispensa qualquer algoritmo de escala que não altere a ordem da lista. Isso porque a seleção baseia-se apenas nos índices (o que é equivalente a uma escala por ranking), e não nos scores, para escolha dos indivíduos. O que pode representar um bom ganho de performance.</p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[Algoritmos Genéticos - Parte 3]]></title>
<link>http://sofiaia.wordpress.com/?p=25</link>
<pubDate>Tue, 15 Jul 2008 03:32:46 +0000</pubDate>
<dc:creator>vinigodoy</dc:creator>
<guid>http://sofiaia.wordpress.com/?p=25</guid>
<description><![CDATA[Números aleatórios
Antes de falarmos sobre o algoritmo genético, devo citar que produzi uma class]]></description>
<content:encoded><![CDATA[<p><strong>Números aleatórios</strong></p>
<p>Antes de falarmos sobre o algoritmo genético, devo citar que produzi uma classe para a geração de números aleatórios. Ela utiliza internamente algoritmos da boost, mas fornece uma interface muito mais fácil e intuitiva de usar. A classe chama-se Random, e sua interface é similar a classe de mesmo nome do Java. A classe foi adicionada no namespace sofia::util</p>
<p>[sourcecode language="cpp"]<br />
//------ Random.h<br />
class Random<br />
{<br />
   private:<br />
      boost::mt19937 rng;</p>
<p>   public:<br />
      explicit Random();<br />
      explicit Random(unsigned seed);</p>
<p>      void seed(unsigned seed);<br />
      unsigned nextInt(unsigned max);</p>
<p>      int nextInt(int min, int max);<br />
      double nextDouble();</p>
<p>      float nextFloat();<br />
      bool nextBool();<br />
};</p>
<p>//------ Random.cpp<br />
Random::Random() : rng(static_cast<int>(std::time(0))) {}</p>
<p>Random::Random(unsigned seed) : rng(seed) {}</p>
<p>void Random::seed(unsigned seed)<br />
{<br />
   rng.seed(seed);<br />
}</p>
<p>unsigned Random::nextInt(unsigned range)<br />
{<br />
   if (range == 0)<br />
      return 0;</p>
<p>   boost::uniform_int<unsigned> interval(0,range-1);<br />
   boost::variate_generator<boost::mt19937&, boost::uniform_int<unsigned> ><br />
      die(rng, interval);<br />
   return die();<br />
}</p>
<p>int Random::nextInt(int min, int max)<br />
{<br />
   boost::uniform_int<> interval(min,max);<br />
   boost::variate_generator<boost::mt19937&, boost::uniform_int<> ><br />
      die(rng, interval);<br />
   return die();<br />
}</p>
<p>double Random::nextDouble()<br />
{<br />
   boost::uniform_real<> realInterval(0,1);<br />
   boost::variate_generator<boost::mt19937&, boost::uniform_real<> ><br />
      realRandom(rng, realInterval);<br />
   return realRandom();<br />
}</p>
<p>float Random::nextFloat()<br />
{<br />
   boost::uniform_real<float> realInterval(0,1);<br />
   boost::variate_generator<boost::mt19937&, boost::uniform_real<float> ><br />
      realRandom(rng, realInterval);<br />
   return realRandom();<br />
}</p>
<p>bool Random::nextBool()<br />
{<br />
   return nextInt(100) % 2 == 0;<br />
}<br />
[/sourcecode]</p>
<p><strong>Seleção</strong></p>
<p>Selecionar indivíduos para que se reproduzam é uma das principais necessidades do algoritmo genético. Indivíduos com o maior score devem ter maior chance de serem selecionados, mas indivíduos com score baixo não devem ser totalmente excluídos da seleção.</p>
<p>O SofiaIA disponibiliza 3 tipos de algoritmos de seleção, todos baseados na seguinte interface:</p>
<p>[sourcecode language="cpp"]<br />
template <typename Individual><br />
class SelectionFunction<br />
{<br />
    virtual ScoredPopulation select(ScoredPopulation& population, int amount) = 0;<br />
    virtual ~SelectionFunction() {};<br />
};[/sourcecode]</p>
<p>Alterei o ScoredMultiset para ScoredPopulation e agora, ao invés de usar um MultiSet estou usando um std::vector. Isso porque o multiset não se mostrou prático na hora de fazer o cruzamento, conforme será visto adiante.</p>
<p>O primeiro tipo de seleção é chamado Seleção em Torneio. Basicamente, sorteamos dois indivíduos e adicionamos o de maior score na lista. O único indivíduo que nunca terá chance de ser escolhido é o de menor score. Veja a implementação do algoritmo:</p>
<p>[sourcecode language="cpp"]<br />
template <typename Individual><br />
class TournamentSelection : public SelectionFunction<Individual><br />
{<br />
   private:<br />
      sofia::util::Random random;</p>
<p>   public:<br />
      explicit TournamentSelection() {}<br />
      explicit TournamentSelection(unsigned seed) : random(seed) {}</p>
<p>      virtual ScoredPopulation select(const ScoredPopulation& population, int amount)<br />
      {<br />
        ScoredPopulation selected = new ScoredPopulation();</p>
<p>        for (int i = 0; i < amount; i++)<br />
        {<br />
            ScoredIndividual one = population.get(random.nextInt(population.size()));<br />
            ScoredIndividual two = population.get(random.nextInt(population.size()));<br />
            population.push_back(one > two ? one : two);<br />
        }<br />
        return selected;<br />
      }<br />
};[/sourcecode]</p>
<p>O segundo e o terceiro algoritmo são de uma categoria chamada de algoritmo de roleta. Para entender a analogia do nome, imagine uma roleta, iguais aquelas do programa do Silvio Santos. Um grande círculo dividido em várias faixas, onde cada uma tem a largura proporcional ao score após a aplicação da escala.</p>
<p>Abaixo, está um exemplo de roleta feita a partir de uma população de 20 indíviduos. Observe que os scores sofreram a escala por ranking:</p>
[caption id="attachment_27" align="aligncenter" width="335" caption="Roleta"]<a href="http://sofiaia.files.wordpress.com/2008/07/roleta.png"><img class="size-full wp-image-27" src="http://sofiaia.wordpress.com/files/2008/07/roleta.png" alt="Roleta" width="335" height="334" /></a>[/caption]
<p>A forma que o algoritmo trabalha é a seguinte. Primeiro, pega-se um número entre 0 e a soma de todos os scores. Depois, percorre-se os elementos um-a-um, somando seus scores. Quando um indivíduo tiver seu score somado e esse valor se tornar maior que a soma fornecida inicialmente, ele será adicionado a lista.</p>
<p>Por exemplo, vamos supor que sorteassemos o número 43. Na roleta acima, pegaríamos o terceiro elemento, pois 20 &#60; 43, 20+19=39 &#60; 43, mas 20+19+18=57 e 57 &#62;=43. É dessa forma que "giramos" a roleta.</p>
<p>A classe AbstractWheelSelection implementa essa lógica:</p>
<p>[sourcecode language="cpp"]<br />
template <typename Individual><br />
class AbstractWheelSelection : public SelectionFunction<Individual><br />
{<br />
   protected:<br />
      virtual std::deque<int> generateSums(const ScoredPopulation& population,<br />
          int amount, double sum) = 0;</p>
<p>   public:<br />
      virtual ScoredPopulation select(const ScoredPopulation& population,<br />
          int amount, double sum)<br />
      {<br />
         int sum = 0;<br />
         BOOST_FOREACH(ScoredIndividual individual, population)<br />
         {<br />
            sum += individual.getScore();<br />
         }<br />
         std::deque<int> rouletteResults =<br />
            generateSums(population, amount, sum);<br />
         std::sort(rouletteResults.begin(), rouletteResults.end());</p>
<p>         ScoredPopulation selected = new ScoredPopulation();<br />
         sum = 0;<br />
         BOOST_FOREACH (ScoredIndividual individual, population)<br />
         {<br />
            sum += individual.getScore();<br />
            while (rouletteResults.size() > 0 && rouletteResults.front() < sum)<br />
            {<br />
                selected.push_back(individual);<br />
                rouletteResults.pop_front();<br />
            }<br />
         }<br />
         return selected;<br />
      }<br />
};<br />
[/sourcecode]</p>
<p>Esse algoritmo tem uma otimização, em relação a versão descrita inicialmente. Ele recebe um array ordenado, com o número de somas igual ao número de elementos a serem selecionados. Assim, ele é capaz de pegar todos os indivíduos percorrendo a lista uma única vez.</p>
<p>As variações do algoritmo baseiam-se em diferentes formas de "girar a roleta", ou seja, de se fornecer a soma inicial. E é por isso que o método generateSums permanece virtual puro.</p>
<p>A primeira versão é mais próxima dos talk-shows. Efetivamente giramos a roleta sem saber onde ela vai parar, ou seja, utilizamos valores de soma aleatórios. Esse algoritmo é descrito a seguir:</p>
<p>[sourcecode language="cpp"]<br />
template <typename Individual><br />
class RouletteWheelSelection : public AbstractWheelSelection<Individual><br />
{<br />
   public:<br />
      RouletteWheelSelection() {}<br />
      RouletteWheelSelection(unsigned seed) : random(seed) {}</p>
<p>   private:<br />
      sofia::util::Random random;</p>
<p>   protected:<br />
      virtual std::deque<int> generateSums(const ScoredPopulation& population,<br />
          int amount, double sum)<br />
      {<br />
         std::deque<int> rouletteResults;</p>
<p>         while (rouletteResults.size() < amount)<br />
            rouletteResults.push_back(random.nextInt(0, amount));<br />
         return rouletteResults;<br />
      }<br />
};<br />
[/sourcecode]</p>
<p>A segunda versão do algoritmo gira a roleta em uma quantidade fixa. Imagine a roleta dividida nas fatias proporcionais ao score. Em seguida, imagine que colocamos marcadores, usando uma divisão equalitária, igual ao número de elementos desejados. Então pegamos os elementos das fatias que estiverem em cima dos marcadores. É isso que ocorre no algoritmo conhecido como "Seleção Estocástica Universal":</p>
<p>[sourcecode language="cpp"]<br />
template <typename Individual><br />
class StochasticUniversalSelection : public AbstractWheelSelection<Individual><br />
{<br />
   protected:<br />
      virtual std::deque<int> generateSums(const ScoredPopulation& population,<br />
          int amount, double sum)<br />
      {<br />
         double division = sum / (double)amount;<br />
         std::deque<int> sums;<br />
         for (int i = 0; i < amount; i++)<br />
             sums.push_back(static_cast<int>(i*division));</p>
<p>         return sums;<br />
      }<br />
};<br />
[/sourcecode]</p>
<p><strong>Gerações</strong></p>
<p>Finalmente, chegou a hora de criar uma classe que agrupe todos esses conceitos. É a classe Generation. Ela representa uma geração.O usuário do SofiaIA deve construir a primeira geração de indivíduos. Geralmente, 20 ou 30 indivíduos são suficientes. Então, basta chamar o método next() quantas vezes achar necessário.</p>
<p>Logo que uma geração é criada, ela é completamente avaliada pela função de fitness. O usuário pode já saber quem é o seu melhor indivíduo e qual seu score. A cada chamada ao next, os indivíduos passam pela escala, reprodução e mutação.</p>
<p>Outro conceito que a geração implementa é o de <em>elitismo</em>. Elitismo é um percentual de indivíduos de melhor score que serão transportados de uma geração para outra, sem qualquer tipo de modificação. Ou seja, garantimos que a elite esteja sempre na próxima geração. Isso permite uma convergência mais rápida. Um percentual ideal de elitismo gira em torno de 5%, elitismo alto demais pode levar ao problema da Convergência Prematura, citado ontem.</p>
<p>A geração também aplicará as taxas de cruzamento e uma nova taxa de mutação.</p>
<p>Caso os indivíduos não cruzem, eles são diretamente adicionados na próxima geração. Se tiverem que cruzar, seus filhos é que entrarão na geração seguinte. Uma boa taxa de cruzamento gira em torno de 70 até 80%. O padrão da biblioteca é 75%.</p>
<p>O método de mutação aleatório, descrito no primeiro artigo, podia ter percentuais baixos de mutação. Entretanto, existem outros métodos, que podem ser garantidos. Então, considerei uma boa política também aplicar uma chance de mutação aqui. Se a mutação não ocorrer, o individuo selecionado é diretamente adicionado na próxima geração. Caso contrário, seu método mutate() é chamado e seu resultado entra na próxima geração. Uma boa taxa de mutação deve ser 1% por bit. A SofiaIA usa como padrão 100%, pois assume-se que o usuário utilizará o RandomMutation com 1%.</p>
<p>Eis a implementação da classe:</p>
<p>[sourcecode language="cpp"]<br />
template <typename Individual><br />
class Generation<br />
{<br />
   private:<br />
      unsigned count;</p>
<p>      ScoredPopulation scored;<br />
      FitnessFunction<Individual> fitnessFunction;<br />
      scaling::ScalingFunction<Individual> scalingFunction;<br />
      selection::SelectionFunction<Individual> selectionFunction;</p>
<p>      double crossoverRate;<br />
      double ellitismRate;<br />
      double mutationRate;</p>
<p>      explicit Generation(std::vector<Individual> population,<br />
                          const Generation<Individual>& other)<br />
      : count(other.count+1), fitnessFunction(other.fitnessFunction),<br />
         scalingFunction(other.scalingFunction),<br />
         selectionFunction(other.selectionFunction),<br />
         crossoverRate(other.crossoverRate),<br />
         ellitismRate(other.ellitismRate),<br />
         mutationRate(other.mutationRate)<br />
      {<br />
         doCalculations(population);<br />
      }<br />
   private:<br />
      void doCalculations(const std::vector<Individual> population)<br />
      {<br />
         BOOST_FOREACH(Individual individual, population)<br />
         {<br />
            scored.push_back(Scored(individual,<br />
               fitnessFunction.calculateFitness(individual)));<br />
         }<br />
         std::sort(scored.begin(), scored.end(), std::greater<ScoredIndividual >());<br />
      }</p>
<p>   public:<br />
      explicit Generation(std::vector<Individual>& population,<br />
         const FitnessFunction<Individual>& fitness,<br />
         const scaling::ScalingFunction<Individual>& scaling = scaling::NoScaling<Individual>(),<br />
         const selection::SelectionFunction<Individual>& selection = selection::RouletteWheelSelection<Individual>(),<br />
         double _crossoverRate = 0.75,<br />
         double _mutationRate = 1,<br />
         double _ellitismRate = 0.05)<br />
      : count(1), fitnessFunction(fitness), scalingFunction(scaling),<br />
         selectionFunction(selection), crossoverRate(_crossoverRate),<br />
         mutationRate(_mutationRate), ellitismRate(_ellitismRate)<br />
      {<br />
         doCalculations(population);<br />
      }</p>
<p>      const Individual& getBestIndividual() const<br />
      {<br />
         return scored[0].get();<br />
      }</p>
<p>      unsigned getBestScore() const<br />
      {<br />
         return scored[0].getScore();<br />
      }</p>
<p>      unsigned getCount() const<br />
      {<br />
         return count;<br />
      }</p>
<p>      Generation<Individual> next(unsigned seed = 0)<br />
      {<br />
         std::vector<Individual> next;</p>
<p>         //Separate the elite, if any<br />
         int eliteSize = static_cast<int>(ellitismRate * scored.size());<br />
         int i = 0;<br />
         BOOST_FOREACH(ScoredIndividual i, scored)<br />
         {<br />
            if (i >= eliteSize)<br />
               break;<br />
            next.push_back(i.get());<br />
         }</p>
<p>         ScoredPopulation scaled = scalingFunction.scale(scored);</p>
<p>         //Select candidates for crossover<br />
         ScoredPopulation selected = selectionFunction.select(scaled, scaled.size() - eliteSize);</p>
<p>         //For each selected pair<br />
         for (int i = 0; i < selected.size() - 1; i += 2)<br />
         {<br />
            sofia::util::Random random;<br />
            if (seed > 0) random.seed(seed);</p>
<p>            const Individual& p1 = selected[i].get();<br />
            const Individual& p2 = selected[i+1].get();</p>
<p>            //Cross the selection or not, according to the crossover rate<br />
            std::pair<Individual, Individual> children =<br />
               random.nextDouble() < crossoverRate ? p1.crossover(p2) :<br />
                  std::pair<Individual, Individual>(p1, p2);</p>
<p>            //Mutate the children, if need.<br />
            if (random.nextDouble() < mutationRate)<br />
                children.first.mutate();</p>
<p>            if (random.nextDouble() < mutationRate)<br />
                children.second.mutate();</p>
<p>            //Then, add the elements to the return list<br />
            next.add(children.first);<br />
            next.add(children.second);<br />
         }</p>
<p>         return new Generation<Individual>(next, this);<br />
      }<br />
};[/sourcecode]</p>
<p><strong>Observações</strong></p>
<p>Apesar de toda complicação descrita até aqui, o uso do framework é relativamente simples. O usuário precisaria apenas:</p>
<ol>
<li>Implementar indivíduo, com os métodos crossover e mutate. Para isso, poderá usar a classe auxiliar BitGenome;</li>
<li>Implementar uma função de fitness;</li>
<li>Criar uma nova geração, com aproximadamente 20 indivíduos aleatórios.</li>
<li>Chamar o método next() quantas vezes achar necessário.</li>
</ol>
<p>Da mesma forma, usuários avançados poderiam refinar os métodos de seleção e cruzamento, seja escolhendo opções diferentes disponíves, seja implementando seus próprios métodos ou estrutura de genoma.</p>
<p>Além disso, todos os algoritmos que geram números aleatórios aceitam como parâmetro a semente. Isso permite que o usuário, se desejar, torne o comportamento do algoritmo determinístico. Assim, num jogo de rede, por exemplo, duas máquinas remotas rodando o algoritmo genético sobre a mesma massa de dados obteriam exatamente o mesmo resultado, ainda mantendo um comportamento relativamente aleatório para o ser humano que assiste o jogo.</p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[Algoritmos Genéticos - Parte 2]]></title>
<link>http://sofiaia.wordpress.com/?p=23</link>
<pubDate>Mon, 14 Jul 2008 00:39:10 +0000</pubDate>
<dc:creator>vinigodoy</dc:creator>
<guid>http://sofiaia.wordpress.com/?p=23</guid>
<description><![CDATA[Individual
Hoje, reforcei o conceito de indíviduo para o meu framework. O indivíduo é o responsá]]></description>
<content:encoded><![CDATA[<p><strong>Individual</strong></p>
<p>Hoje, reforcei o conceito de indíviduo para o meu framework. O indivíduo é o responsável por encapsular qual é o tipo de genoma utilizado. Ele também fornece métodos de alto nível para a função de fitness. Por exemplo, um indivíduo que representa um possível retângulo da imagem teria os métodos getX(), getY(), getWidth() e getHeight() e possivelmente outros métodos utilitários, como intersects. Internamente, ele armazenaria esses valores em alguma estrutura de genoma que convier para o usuário do framework, como o BitGenome demonstrado ontem.</p>
<p>No framework, o indivíduo é apenas um argumento de um template. Todo indivíduo deve ser capaz, no entanto de suportar 2 métodos:</p>
<p>O primeiro é o mutate(). Ele força o indivíduo a sofrer uma mutação. Exatamente como essa mutação ocorre é definido pelo implementador do indivíduo, portanto, o usuário da SofiaIA. Ontem vimos possíveis políticas par ao caso do genoma baseado em bits.</p>
<p>O segundo é o cross. Cada indivíduo deve ser capaz de cruzar com outro indivíduo da mesma espécie e gerar 2 novos indivíduos. O BitGenome também já implementa alguns tipos de cruzamento pré-definidos.</p>
<p><strong>ScoredIndividuals</strong></p>
<p>Todo individuo, cedo ou tarde, receberá um score. Aliás, atribuir scores é uma tarefa muito comum em vários tipos de algoritmos de IA. Portanto, uma classe imutável simples, que contém um elemento qualquer e um score foi criada para facilitar essa tarefa:</p>
<p>Ela se encontra no namespace util, e será usada durante a implementação do genético:</p>
<p>[sourcecode language="cpp"]<br />
template <typename T><br />
class Scored<br />
{<br />
   private:<br />
      T elem;<br />
      unsigned score;<br />
   public:<br />
      explicit Scored(const T& _elem, unsigned _score)<br />
      : elem(_elem), score(score) {}</p>
<p>      const T& get() const { return elem; }<br />
      unsigned getScore() const { return score; }<br />
};<br />
[/sourcecode]</p>
<p><strong>Atribuição da nota</strong></p>
<p>Todas as notas são atribuídas através de uma função de fitness. Basicamente, a função de fitness recebe um indivíduo, observa seus atributos, e atribui a ele um escore. Quem implementa a função de fitness integralmente é o usuário da SofiaIA. A função de Fitness, na biblioteca, é definida pela seguinte interface:</p>
<p>[sourcecode language="cpp"]<br />
template <typename Individual><br />
class FitnessFunction<br />
{<br />
    virtual unsigned calculateFitness(Individual individual) = 0;<br />
    virtual ~FitnessFunction();<br />
};<br />
[/sourcecode]</p>
<p><strong>Escala das notas</strong></p>
<p>O algoritmo genético baseia-se em aleatoriedade. Pode ocorrer uma situação em que, um determinado indivíduo receba uma nota muito maior do que os demais. Esse indivíduo provavelmente cruzará mais e o algoritmo convergirá rapidamente para indica-lo como possível resposta. Entretanto, outra resposta melhor, em outro ponto, poderia ter sido encontrada. Essa situação é chamada de Convergência Prematura.</p>
<p>Outra situação indesejável ocorre mais ao final do processo, quando muitos indivíduos são parecidos demais e o algoritmo fica estagnado em um único ponto.</p>
<p>Para evitar esses problemas, podemos aplicar uma função de escala em todos os scores. O SofiaIA suporta 3 tipos de escalas possíveis, a partir da seguinte interface:</p>
<p>[sourcecode language="cpp"]<br />
template <typename Individual><br />
class ScalingFunction<br />
{<br />
   public:<br />
      virtual ScoredMultiset scale(const ScoredMultiset& population) = 0;<br />
      virtual ~ScalingFunction() {};<br />
};<br />
[/sourcecode]</p>
<p>O ScoredMultiset nada mais é do que uma macro. Ele representa um std::multiset de individuos com escore (usando a classe utilitária citada acima). Outra macro como essa utilizada é a ScoredIndividual. Adotei esse esquema porque não quero incluir o comando using em arquivos .h, mas ainda quero manter a clareza do código. Os leitores devem concordar que é melhor ler:</p>
<p><em>virtual ScoredMultiset scale(const ScoredMultiset&#38; population) = 0;</em></p>
<p>do que:</p>
<p><em>virtual std::multiset&#60;sofia::util::Scored&#60;Individual&#62; &#62; scale(<br />
const std::multiset&#60;sofia::util::Scored&#60;Individual&#62; &#62;&#38; population) = 0;</em></p>
<p>O primeiro tipo de escala disponível é chamado de RankScaling. Nada mais é do que atribuir ao indivíduo de menor score a nota 0, ao de segundo menor a nota 1 e assim sucessivamente, de modo que o melhor indivíduo terá a nota igual ao tamanho da lista - 1.</p>
<p>[sourcecode language="cpp"]<br />
template <typename Individual><br />
class RankScaling : public ScalingFunction<Individual><br />
{<br />
   public:<br />
    ScoredMultiset scale(const ScoredMultiset& population)<br />
    {<br />
      ScoredMultiset scaled;</p>
<p>      int i = 0;<br />
      BOOST_FOREACH(ScoredIndividual scored, population)<br />
      {<br />
         scaled.add(ScoredIndividual(scored.get(), i++));<br />
      }</p>
<p>      return scaled;<br />
    }<br />
};<br />
[/sourcecode]</p>
<p>Como vocês devem ter notado, optei por usar a biblioteca <a title="Boost.org" href="http://www.boost.org/" target="_blank">boost</a> de agora em diante. Porém, para manter a política de que a SofiaIA deve ser fácil de utilizar, vou tentar me ater somente aos trechos da biblioteca que não exigem compilação. O resto do código será remodelado posteriormente para usar mais intensivamente a biblioteca.</p>
<p>O segundo tipo de escala é chamada de SigmaTruncation e usa o cálculo do desvio padrão. Esse tipo de escala é útil quando os escores são muito próximos, e queremos destacar os indivíduos que se distanciaram mais da média. Computacionalmente é a função de escala mais pesada, é famoso por obter bons resultados em populações muito homogêneas.</p>
<p>A constante c permite-nos dizer o quão afastado queremos que os resultados estejam, e é um número que varia usualmente de até 3.</p>
<p>[sourcecode language="cpp"]<br />
template <typename Individual><br />
class SigmaTruncation : public ScalingFunction<Individual><br />
{<br />
   private:<br />
       double c;</p>
<p>   public:<br />
       SigmaTruncation(double _c) : c(_c)<br />
       {}</p>
<p>       ScoredMultiset scale(const ScoredMultiset& population)<br />
       {<br />
         //Calculate the average<br />
         double sum = 0;<br />
         BOOST_FOREACH(ScoredIndividual scored, population)<br />
         {<br />
            sum += scored.getScore();<br />
         }</p>
<p>         //Calculate the standard deviation (sigma)<br />
         double sum2 = 0;<br />
         double avg = sum / population.size();</p>
<p>         BOOST_FOREACH(ScoredIndividual scored, population)<br />
         {<br />
            double dif = scored.getScore() - avg;<br />
            sum2 += dif * dif;<br />
         }<br />
         double sigma = sqrt(sum2 / (population.size() - 1));</p>
<p>         //Finally, calculate the fitness<br />
         ScoredMultiset scoredPopulation;<br />
         BOOST_FOREACH(ScoredIndividual scored, population)<br />
         {<br />
            int fitness = static_cast<int>(scored.getScore() - (avg - c * sigma));<br />
            scoredPopulation.insert(ScoredIndividual(scored, fitness < 0 ? 0 : fitness));<br />
         }<br />
         return scoredPopulation;<br />
       }<br />
};<br />
[/sourcecode]</p>
<p>O terceiro tipo de escala é a ausência de escala. Sua implementação é bem direta:</p>
<p>[sourcecode language="cpp"]<br />
template <typename Individual><br />
class NoScaling : public ScalingFunction<Individual><br />
{<br />
   public:<br />
      virtual ScoredMultiset scale(const ScoredMultiset& population)<br />
      {<br />
         return ScoredMultiset(population);<br />
      };<br />
};<br />
[/sourcecode]</p>
<p>Ele simplesmente copia o multiset de entrada no de resultado. Obviamente é o método mais rápido e é muito útil quando a função de fitness dá resultados precisos.</p>
<p>Obviamente, o usuário ainda é livre para implementar sua própria função de escala, caso queira.</p>
<p><strong>O que falta</strong></p>
<ul>
<li>Melhorar a integração com a boost:
<ul>
<li>Provavelmente será possível reduzir o número de cópias usando shared_ptr.</li>
<li>Também é possível usar os geradores de números aleatórios da boost, em substituição ao péssimo gerador do C++;</li>
</ul>
</li>
<li>Criar os algoritmos de seleção e representação da população;</li>
<li>Elaborar um exemplo de uso e testar as classes.</li>
</ul>
]]></content:encoded>
</item>
<item>
<title><![CDATA[Complejidad Algorítmica]]></title>
<link>http://poncos.wordpress.com/?p=11</link>
<pubDate>Sun, 13 Jul 2008 21:53:55 +0000</pubDate>
<dc:creator>poncos</dc:creator>
<guid>http://poncos.wordpress.com/?p=11</guid>
<description><![CDATA[La teoría de la complejidad algorítmica tiene como objetivo  clasificar cualquier problema que se ]]></description>
<content:encoded><![CDATA[<p>La teoría de la complejidad algorítmica tiene como objetivo  clasificar cualquier problema que se pueda computar  atendiendo al esfuerzo computacional requerido para su resolución.  Para medir dicha complejidad, no se tienen en cuenta destalles de bajo nivel acerca de las características hardware de la máquina, y nos centramos en los detalles del algoritmo en sí, de manera que nos fijaremos en la frecuencia  de ejecución de las instrucciones del algoritmo.</p>
<p>(1)    a = 1;</p>
<p>(2)    <strong>desde</strong> i=1 <strong>hasta</strong> n <strong>hacer</strong></p>
<p>a = a+i;</p>
<p>(3)    <strong>desde</strong> j=1 <strong>hasta</strong> n <strong>hacer</strong></p>
<p><strong>desde</strong> k=1 <strong>hasta</strong> n <strong>hacer</strong></p>
<p>a = a+j+k</p>
<p>En este caso la complejidad  para cada segmente de código es O(1)  para el segmente (1), O(n) para el segmente (2) y O(n<sup>2</sup>) para el segmente (3). Así denotamos la complejidad de un algoritmo con la expresión O(g(n)).</p>
<p style="text-align:center;">O(1) &#60; O(log n) &#60; O(n)  &#60; O(n log n) &#60; O(n<sup>2</sup>) &#60; O (n<sup>3</sup>) &#60; O(2<sup>n</sup>)</p>
<p style="text-align:justify;">En estos momentos disponemos de una medida estándar que nos permitirá expresar la eficiencia computacional de un algoritmo, y comparar diferentes soluciones a un mismo problema. Por ejemplo el algoritmo de ordenación QuickSort, tiene una complejidad del orden de O(n log n) <span style="text-decoration:underline;color:#c0504d;">[1]</span> siendo n el tamaño del vector a ordenar, y el algoritmo de la burbuja del orden de O(n<sup>2</sup>) <span style="text-decoration:underline;color:#c0504d;">[2]</span>, de manera que podemos decir que en circunstancias normales, el algoritmo quicksort es más eficiente.</p>
<p style="text-align:justify;">Una vez disponemos de una manera de expresar la complejidad algorítmica, podemos comenzar a analizar cualquier problema computacional que se nos ocurra y obtener de la misma manera la complejidad algorítmica, pero desgraciadamente, el mundo no es perfecto, y en algún momento se nos ocurrirá algún problema para el que no exista ningún algoritmo que se pueda resolver en un tiempo polinomial expresado con la notación anterior. Aquellos problemas para los que exista un algoritmo que lo soluciones en un tiempo polinomial se dice que pertenecen a la <strong>clase P</strong> mientras que aquellos problemas para los que no se puede diseñar un algoritmo que se resuelva en un tiempo polinomial se les conoce como <strong>problemas de clase NP</strong><br />
<span style="text-decoration:underline;color:#c0504d;">[3]</span>(nodeterministic polinomial problems). Si un problema de tipo NP se pude reformular en tiempo polinomial en otro problema NP, se dice que dicho problema pertenece a la clase <strong>NP-completo </strong><span style="text-decoration:underline;color:#c0504d;">[4]</span>, de manera que si en algún momento se descubre un algoritmo que solucione en un tiempo polinomial dicho problema, automáticamente se habrán resuelto todos los demás problemas NP de dicha clase, puesto que se pueden convergen hacía este.</p>
<p style="text-align:justify;">
<p style="text-align:justify;">Aquellos problemas que pertenecen a la clase NP, son problemas que aunque teóricamente se conoce el algoritmo que lo resolvería, este necesitará muchísimo tiempo (por lo menos en el peor de los casos) encontrar la solución, haciendo que no sean viables. Como ejemplo de dichos problemas:</p>
<ul>
<li>
<div style="text-align:justify;"><strong>Problema del viajante (o entrutado)</strong> <span style="text-decoration:underline;color:#c0504d;"> [5]</span>: este problema consiste en que partiendo de un conjunto de ciudades C = {C<sub>1</sub>, C<sub>2</sub>, … C<sub>n</sub>} deberemos encontrar una combinación que nos permita recorrerlas todas una y solo una vez minimizando la distancia totas recorrida. Como he dicho antes, el algoritmo que soluciones este problema, a priori es sencillo, simplemente deberemos comparar todas las posibles combinación de ciudades posibles y obtener aquella que minimiza la distancia. El problema radica en que a medida que aumenta el número n de ciudades la cantidad de combinaciones posibles de ciudades aumenta exponencialmente (n-1)!/2.</div>
</li>
</ul>
<p style="text-align:justify;margin-left:35pt;">Para n = 10, unas 181.000 combinaciones.</p>
<p style="text-align:justify;margin-left:35pt;">Para n = 20, unas 10.000.000.000.000.000 soluciones posibles.</p>
<p style="text-align:justify;margin-left:35pt;">Para n = 50, … habrá que calcularlo, pero son muchísimas combinaciones posibles.</p>
<ul>
<li>
<div style="text-align:justify;"><strong>Problema de la asignación</strong> <span style="text-decoration:underline;color:#c0504d;">[6]</span></div>
</li>
<li>
<div style="text-align:justify;"><strong>Problema de la mochila</strong> <span style="text-decoration:underline;color:#c0504d;">[7]</span></div>
</li>
<li>
<div style="text-align:justify;">…</div>
</li>
</ul>
<p style="text-align:justify;">Queda claro, que para abarcar la solución de este tipo de problemas, se hace necesario cambiar de táctica, al no poder utilizar las soluciones tradicionales recorriendo todo el espacio de soluciones y devolviendo la mejor de todas. Como técnicas posibles para este tipo de problemas podemos citar:</p>
<ul>
<li>
<div style="text-align:justify;"><strong>Técnicas heurísticas:</strong> utilizan "meta-información" que ofrezca "conocimiento" al algoritmo hacer de lo buena que es una solución y así poder guiar la búsqueda en el espacio de soluciones, de manera que podamos obtener en un tiempo razonable una solución que aun no siendo la mejor, represente una solución buena.</div>
</li>
<li>
<div style="text-align:justify;"><strong>Algoritmos genéticos:</strong> se inspiran en los mecanismos que la propia naturaleza utiliza para hacer evolucionar las especies haciendo que generación tras generación se mejoren los resultados.</div>
</li>
<li>
<div style="text-align:justify;"><strong>Redes neuronales: </strong><a href="http://poncos.wordpress.com/2008/03/17/introduccion-a-las-redes-neuronales/" target="_blank">podéis ver mi post sobre introducción a las redes neuronales</a>.</div>
</li>
<li>
<div style="text-align:justify;"><strong>Búsqueda tabú </strong> <span style="text-decoration:underline;color:#c0504d;">[8]</span>.</div>
</li>
<li>
<div style="text-align:justify;"><strong>Optimización basada en colonias de hormigas</strong><span style="text-decoration:underline;color:#c0504d;"> [9]</span>.</div>
</li>
<li>
<div style="text-align:justify;">…</div>
</li>
</ul>
<h1>Referencias</h1>
<p style="text-align:justify;">
<p style="text-align:justify;">[1]    <a href="http://es.wikipedia.org/wiki/Quicksort">http://es.wikipedia.org/wiki/Quicksort</a></p>
<p style="text-align:justify;">[2]    <a href="http://es.wikipedia.org/wiki/Bubblesort">http://es.wikipedia.org/wiki/Bubblesort</a></p>
<p style="text-align:justify;">[3]    <a href="http://es.wikipedia.org/wiki/Clases_de_complejidad_P_y_NP">http://es.wikipedia.org/wiki/Clases_de_complejidad_P_y_NP</a></p>
<p style="text-align:justify;">[4]    <a href="http://es.wikipedia.org/wiki/NP-completo">http://es.wikipedia.org/wiki/NP-completo</a></p>
<p style="text-align:justify;">[5]    <a href="http://es.wikipedia.org/wiki/Problema_del_viajante">http://es.wikipedia.org/wiki/Problema_del_viajante</a></p>
<p style="text-align:justify;">[6]    <a href="http://en.wikipedia.org/wiki/Assignment_problem">http://en.wikipedia.org/wiki/Assignment_problem</a></p>
<p style="text-align:justify;">[7]    <a href="http://es.wikipedia.org/wiki/Problema_de_la_mochila">http://es.wikipedia.org/wiki/Problema_de_la_mochila</a></p>
<p style="text-align:justify;">[8]    <a href="http://en.wikipedia.org/wiki/Tabu_search">http://en.wikipedia.org/wiki/Tabu_search</a></p>
<p style="text-align:justify;">[9]    <a href="http://en.wikipedia.org/wiki/Ant_colony_optimization">http://en.wikipedia.org/wiki/Ant_colony_optimization</a></p>
<p style="text-align:justify;">
]]></content:encoded>
</item>
<item>
<title><![CDATA[Algoritmos Genéticos]]></title>
<link>http://sofiaia.wordpress.com/?p=21</link>
<pubDate>Sun, 13 Jul 2008 05:22:19 +0000</pubDate>
<dc:creator>vinigodoy</dc:creator>
<guid>http://sofiaia.wordpress.com/?p=21</guid>
<description><![CDATA[Algoritmo genético é um tipo de algoritmo da categoria dos algoritmos de busca estocástica. Ele b]]></description>
<content:encoded><![CDATA[<p>Algoritmo genético é um tipo de algoritmo da categoria dos algoritmos de busca estocástica. Ele baseia-se na genética para realizar pesquisa. É muito útil quando você não tem nem idéia de onde a solução possa estar, mas é capaz de avaliar a qualidade de uma determinada resposta, seja ela qual for.</p>
<p>Darei como exemplo um problema que meus alunos estão tentando resolver: encontrar a placa de um veículo numa foto. A única coisa que nós sabemos de antemão é que a placa está lá. Não sabemos o tamanho que ela aparecerá e nem em que posição da foto.</p>
<p>Entretanto, não é muito complicado montar um algoritmo que diga se uma determinada região da imagem é uma placa ou não, desde que ele receba de entrada o "retângulo" correspodente a essa região. Poderíamos testar se esse retângulo é quase totalmente branco, com algum percentual de preto no meio (para as letras).</p>
<p>Notamos aí duas características:</p>
<ol>
<li>Temos uma série infinita de retângulos possíveis numa imagem, de tamanhos diferentes;</li>
<li>Temos uma forma de dar uma nota num desses retângulo.</li>
</ol>
<p>Todo algoritmo genético se baseia em quatro fases, aplicada sobre uma população (no caso, um conjunto desses retângulos). Ao final das quatro fases, temos uma nova população.</p>
<ul>
<li><strong>Avaliação (Fitness): </strong>Dada uma população, damos um escore para cada um deles. O de melhor escore estará mais próximo da possível solução;</li>
<li><strong>Seleção (Selection): </strong>Escolhemos alguns indivíduos dessa população. Geralmente, indivíduos de melhor score tem mais chance de serem escolhidos, como seria na natureza.</li>
<li><strong>Cruzamento (Crossover): </strong>Cruzamos alguns desses indivíduos, combinando seus genes. Outros, deixamos intocados para a próxima geração (como se tivessem "sobrevivido"). O ideal é que as taxas de cruzamento sejam altas, em torno de 70%;</li>
<li><strong>Mutação (Mutation): </strong>Alguns dos indivíduos sofrem mutações aleatórias. As taxas de mutação recomendadas giram em torno de 1%.</li>
</ul>
<p><strong>Genoma em bits</strong></p>
<p>Antes de iniciar as fases e o trabalho sobre os indivíduos, precisamos representar de alguma forma as suas características. Como programadores, logo nos vem a cabeça as variáveis.</p>
<p>Entretanto, assim como na genética, poderíamos guardar as características de um desses retângulos através de um <em>genoma</em>. No caso do corpo humano, esse genoma é o DNA. No caso da informática, podemos usar um std::bitset, um std::vector&#60;bool&#62; ou qualquer outra estrutura para representar o genoma (até mesmo uma árvore). Hoje, me concentrei em montar uma estrutura adequada para representar um genoma na forma de bits.</p>
<p>Ok, vamos supor que nossa imagem tenha no máximo 1024x1024 pixels. É um bom tamanho. Os retângulos podem iniciar em qualquer ponto da imagem, então poderíamos organizar nosso genoma com 40 bits: 10 para o x, 10 para y, 10 para a altura e 10 para largura.</p>
<p>Não é difícil perceber que é necessário uma classe conveniente para manipular esses bits. Ao olhar a STL me deparei com 2 opções:</p>
<ol>
<li>A classe BitSet, que representa um mapa de bits de tamanho fixo;</li>
<li>A classe vector&#60;bool&#62; que representa um mapa de bits de tamanho variável.</li>
</ol>
<p>A vantagem do BitSet sobre o vector é o fato dele ocupar um pouco menos espaço e de ter métodos mais específicos mais convenientes para a manipulação de bits. A do vector é o fato de cada bit poder ser acessado em tempo linear, próximo de 0, além de ser considerado um container padrão.</p>
<p>Como a IA é famosa por ser pesada, e os algoritmos genéticos não são exceção a essa regra, optei pela classe vector, que tem maior performance. Montei então uma classe chamada BitGenome, que permitiria que um programador facilmente lesse e gravasse tipos inteiros na estrutura:</p>
<p>A classe também tem métodos para fazer a mutação e a cruza, baseado em algoritmos fornecidos externamente. Explicarei esses algoritmos na sequência. Ela está situada no namespace sofia::genetic::bit, omitirei aqui as declarações de namespace para melhorar a formatação para o blog:</p>
<p>[sourcecode language="cpp"]<br />
//BitGenome.h<br />
class BitGenome<br />
{<br />
   private:<br />
      std::vector<bool> genes;</p>
<p>   public:<br />
      explicit BitGenome(int _size);</p>
<p>      void setUnsigned(int pos, unsigned long number, int bits);<br />
      void setSigned(int pos, long number, int bits);</p>
<p>      unsigned long getUnsigned(int pos, int bits) const;<br />
      long getSigned(int pos, int bits) const;</p>
<p>      void set(int bit, bool value);<br />
      bool get(int bit) const;<br />
      bool operator[](int bit) const;</p>
<p>      void mutate(BitMutationMethod& mutationMethod);<br />
      std::pair<BitGenome, BitGenome> crossover(const BitGenome& other,<br />
         BitCrossoverMethod& crossoverFunctor) const;</p>
<p>      int size() const;<br />
};</p>
<p>//BitGenome.cpp<br />
BitGenome::BitGenome(int _size)<br />
: genes(_size) {}</p>
<p>void BitGenome::setUnsigned(int pos, unsigned long number, int bits)<br />
{<br />
   unsigned long max = ((2 << bits - 1) - 1);</p>
<p>   if (number > max)<br />
   {<br />
       std::stringstream ss;<br />
       ss << "Invalid number " << number << "! ";<br />
       ss << "Maximum value for " << bits << " bits is " << max << "!";<br />
       throw std::out_of_range(ss.str());<br />
   }</p>
<p>   for (int i = pos + bits - 1; i >= pos; i--)<br />
   {<br />
      genes[i] = (number & 1) == 1;<br />
      number = number >> 1;<br />
   }<br />
}</p>
<p>void BitGenome::setSigned(int pos, long number, int bits)<br />
{<br />
   if (number < 0)<br />
   {<br />
      setUnsigned(pos + 1, -number, bits - 1);\<br />
      genes[pos] = true;<br />
      return;<br />
   }</p>
<p>   setUnsigned(pos + 1, number, bits - 1);<br />
   genes[pos] = 0;<br />
}</p>
<p>unsigned long BitGenome::getUnsigned(int pos, int bits) const<br />
{<br />
   unsigned long num = 0;</p>
<p>   for (int i = pos; i < pos + bits; i++)<br />
      num = (num << 1) + (genes[i] ? 1 : 0);</p>
<p>   return num;<br />
}</p>
<p>long BitGenome::getSigned(int pos, int bits) const<br />
{<br />
   long num = getUnsigned(pos + 1, bits - 1);<br />
   return genes[pos] ? -num : num;<br />
}</p>
<p>void BitGenome::set(int bit, bool value)<br />
{<br />
   genes[bit] = value;<br />
}</p>
<p>bool BitGenome::get(int bit) const<br />
{<br />
   return genes[bit];<br />
}</p>
<p>bool BitGenome::operator[](int bit) const<br />
{<br />
   return get(bit);<br />
}</p>
<p>void BitGenome::mutate(BitMutationMethod& mutationMethod)<br />
{<br />
   mutationMethod.mutate(*this);<br />
}</p>
<p>std::pair<BitGenome, BitGenome> BitGenome::crossover(const BitGenome& other, </p>
<p>BitCrossoverMethod& crossoverMethod) const<br />
{<br />
   if (size() != other.size())<br />
      throw std::invalid_argument("Incompatible genomes!");</p>
<p>   return crossoverMethod.crossover(*this, other);<br />
}</p>
<p>int BitGenome::size() const<br />
{<br />
   return genes.size();<br />
}<br />
[/sourcecode]</p>
<p>Note que números unsigned são armazenados como complementos de 1, não de 2, pois encontrei alguns artigos que faziam essa recomendação. A classe ainda não tem suporte a tipos float ou double. Essa última deficiência pode ser contornada usando aritmética de ponto fixo.</p>
<p><strong>Cruzamentos</strong></p>
<p>Dois individuos sexuados (e no caso desses algoritmos, todos são) podem cruzar e compartilhar genes. Há várias políticas que descrevem como fazer isso. A interface que representa uma política qualquer é a classe CrossoverMethod, descrita abaixo (novamente, namespace foi omitido):</p>
<p>[sourcecode language="cpp"]<br />
//BitCrossoverMethod.h</p>
<p>class BitGenome;</p>
<p>class BitCrossoverMethod<br />
{<br />
   public:<br />
      virtual std::pair<BitGenome, BitGenome> crossover(const BitGenome& genome1,<br />
          const BitGenome& genome2);<br />
      virtual ~BitCrossoverMethod();<br />
};<br />
[/sourcecode]</p>
<p>Note que cada crossover resulta em 2 filhos. Um deles sendo a aplicação dos genes do pai sobre a mãe, e vice-versa.</p>
<p>Duas políticas já estão implementadas na SofiaIA. A primeira é a chamada PointCrossover. Ela consiste em escolher alguns pontos de corte para a troca dos genes, e alternar os genes dos pais e dos filhos nesses pontos. Por exemplo, suponha os genomas 0000000 e 1111111 e os pontos de corte 2 e 5. Eles resultariam no seguinte:</p>
<p>pai:   00&#124;000&#124;00   mãe: 11&#124;111&#124;11   filho1 - 0011100   filho2 - 1100011</p>
<p>Abaixo a implementação do algoritmo:</p>
<p>[sourcecode language="cpp"]<br />
//PointCrossover.h<br />
class PointCrossover : public BitCrossoverMethod<br />
{<br />
   private:<br />
      std::set<int> cutSet;</p>
<p>   public:<br />
      explicit PointCrossover(const std::set<int>& _cutSet);</p>
<p>      virtual std::pair<BitGenome, BitGenome> crossover(const BitGenome& genome1,<br />
            const BitGenome& genome2);<br />
};</p>
<p>//PointCrossover.cpp<br />
PointCrossover::PointCrossover(const std::set<int>& _cutSet)<br />
: cutSet(_cutSet) {}</p>
<p>std::pair<BitGenome, BitGenome> PointCrossover::crossover(const BitGenome& genome1,<br />
       const BitGenome& genome2)<br />
{<br />
   std::pair<BitGenome, BitGenome> children(genome1, genome1);</p>
<p>   bool flip = false;</p>
<p>   for (int i = 0; i < genome1.size(); i++)<br />
   {<br />
      if (cutSet.find(i) != cutSet.end())<br />
          flip = !flip;</p>
<p>      children.first.set(i, flip ? genome1.get(i) : genome2.get(i));<br />
      children.second.set(i, flip ? genome2.get(i) : genome1.get(i));<br />
   }</p>
<p>   return children;<br />
}<br />
[/sourcecode]</p>
<p>Amanhã inserirei um segundo construtor, que aceita varargs. Isso deve tornar o uso prático.Alguns autores diferenciam crossovers simples de múltiplos. Note que o algoritmo trata ambos os casos.</p>
<p>Outro método de cruza é o chamado cruza uniforme. Basicamente, escolhe-se uma taxa, que varia de 0 até 1. Então, para cada bit, sorteia-se um número, também de 0 até 1. Se o número for menor que a taxa, aquele bit é trocado. Caso contrário, o bit se mantém. Note que esse algoritmo, se a taxa for suficientemente pequena, pode gerar uma prole igual aos pais.</p>
<p>Abaixo, segue o algoritmo:</p>
<p>[sourcecode language="cpp"]<br />
//UniformCrossover.h<br />
class UniformCrossover : public BitCrossoverMethod<br />
{<br />
   private:<br />
      float ratePerBit;</p>
<p>   public:<br />
      explicit UniformCrossover(float _ratePerBit);<br />
      virtual std::pair<BitGenome, BitGenome> crossover(const BitGenome& genome1,<br />
          const BitGenome& genome2);<br />
};</p>
<p>//UniformCrossover.cpp<br />
UniformCrossover::UniformCrossover(float _ratePerBit)<br />
: ratePerBit(_ratePerBit) {}</p>
<p>std::pair<BitGenome, BitGenome> UniformCrossover::crossover(const BitGenome& genome1,<br />
    const BitGenome& genome2)<br />
{<br />
   std::pair<BitGenome, BitGenome> children(genome1, genome1);<br />
   std::srand(std::time(NULL));</p>
<p>   int minimum = static_cast<int>(ratePerBit * RAND_MAX);</p>
<p>   for (int i = 0; i < genome1.size(); i++)<br />
   {<br />
      if (std::rand() < minimum)<br />
      {<br />
         children.first.set(i, genome2[i]);<br />
         children.second.set(i, genome1[i]);<br />
      }<br />
      else<br />
      {<br />
         children.first.set(i, genome1[i]);<br />
         children.second.set(i, genome2[i]);<br />
      }<br />
   }</p>
<p>   return children;<br />
}<br />
[/sourcecode]</p>
<p>O usuário ainda é livre para esterder diretamente a classe BitCrossover e implementar sua própria política de cruzamento, se quiser.</p>
<p><strong>Mutação</strong></p>
<p>Além de cruzar, indivíduos também podem sofrer mutação. Isso permite que o algoritmo teste valores arbitrários, que podem conter um possível resultado. Assim como no crossover, a classe BitMutationMethod representa uma política de mutação qualquer:</p>
<p>[sourcecode language="cpp"]<br />
class BitMutationMethod<br />
{<br />
   public:<br />
      virtual void mutate(BitGenome& genome) = 0;<br />
      virtual ~BitMutationMethod() {};<br />
};<br />
[/sourcecode]</p>
<p>A mutação no caso de um genoma baseada em bits é muito simples. Basta escolher uma taxa e mudar os bits aleatoriamente, dentro daquela taxa. Mais ou menos como fizemos para alternar os bits no UniformCrossover. Políticas mais específicas geralmente são implementadas dentro do domínio do problema, isso é, pelo usuário da SofiaIA. A política de mutação baseada em random é implementada na classe RandomMutation, descrita abaixo:</p>
<p>[sourcecode language="cpp"]<br />
//RandomMutation.h<br />
class RandomMutation : public BitMutationMethod<br />
{<br />
   private:<br />
      float ratePerBit;</p>
<p>   public:<br />
      explicit RandomMutation(float _ratePerBit);<br />
      virtual void mutate(BitGenome& genome);<br />
      virtual ~RandomMutation();<br />
};</p>
<p>//RandomMutation.cpp<br />
RandomMutation::RandomMutation(float _ratePerBit)<br />
: ratePerBit(_ratePerBit) {}</p>
<p>void RandomMutation::mutate(BitGenome& genes)<br />
{<br />
   std::srand(std::time(NULL));<br />
   int minimum = static_cast<int>(ratePerBit * RAND_MAX);</p>
<p>   for (int i = 0; i < genes.size(); i++)<br />
      if (std::rand() < minimum)<br />
         genes.set(i, !genes.get(i));<br />
}<br />
[/sourcecode]</p>
<p><strong>O que poderia melhorar</strong></p>
<ul>
<li>Como já citado, ainda falta incluir um construtor com varargs na classe PointCrossover;</li>
<li>Seria necessário encontrar uma função de randomização melhor. Estou pensando em usar uma das classes da boost, ou implementar uma;</li>
<li>É necessário incluir método para manipulação de números de ponto flutuante no BitGenome.</li>
<li>É necessário comprovar que trabalhar com complementos de 1 é realmente vantajoso.</li>
</ul>
<p><strong>Onde obter mais informações</strong></p>
<p>O melhor material que já achei sobre o assunto está <a title="Prever cap�tulo" href="http://books.google.com/books?id=mDcRYavIn2MC&#38;pg=PA413&#38;lpg=PA413&#38;source=web&#38;ots=9woaP9FUMB&#38;sig=wCDykzvJj_NeBwlh9gpGhRpF8mk&#38;hl=pt-BR&#38;sa=X&#38;oi=book_result&#38;resnum=6&#38;ct=result" target="_blank">no livro do Brian Schwab, AI Game Engine Programming</a>.</p>
<p>O Norvig traz brevemente o tema, mas nada digno de nota.</p>
<p>Outro bom material está nesse site, e que tem tradução para o português!<br />
<a href="http://www.obitko.com/tutorials/genetic-algorithms/portuguese/" target="_blank">http://www.obitko.com/tutorials/genetic-algorithms/portuguese/</a></p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[Máquina de Estados]]></title>
<link>http://sofiaia.wordpress.com/?p=19</link>
<pubDate>Fri, 11 Jul 2008 21:21:41 +0000</pubDate>
<dc:creator>vinigodoy</dc:creator>
<guid>http://sofiaia.wordpress.com/?p=19</guid>
<description><![CDATA[Finalmente posso retomar o projeto! Depois de meses parado graças as aulas que dei na escola técni]]></description>
<content:encoded><![CDATA[<p>Finalmente posso retomar o projeto! Depois de meses parado graças as aulas que dei na escola técnica, decidi voltar implementando uma classe para lidar com máquinas de estados. Na verdade, isso porque recentemente fiz uma muito parecida para Java, num jogo de pong, e vi o quão importante a classe é.</p>
<p>A classe segue a idéia do prof. Pozzer, e usa uma pilha para "memorizar" os estados passados. Assim, um estado pode solicitar o retorno ao estado anterior, o que simplifica drásticamente a construção de máquinas mais complexas, sobretudo de jogos RTS. Em jogos assim, retornar estados é muito comum. Um exemplo disso é o seguinte:</p>
<p>1. Madeireiro está no estado "CortandoLenha". Chega um soldado inimigo, ele muda para o estado "Fugindo";<br />
2. Ele se afasta, até que o soldado para de persegui-lo e vai para uma batalha. Decide então voltar ao estado "CortandoLenha";<br />
3. Mas ele está longe das árvores! Então, empilha o estado "AndarAtéAFloresta";<br />
4. Após chegar na floresta, desempilha o estado e volta ao "CortandoLenha".</p>
<p>A grande vantagem desse esquema é que cada estado pode ser modelado através de uma série de pré-condições e ações do estado. Se um estado não satisfaz a pré-condição, um estado que busca essa pré-condição é empilhado. Assim, a entidade pode apenas empilhar o estado <strong>final</strong> desejado, um "objetivo". E a própria classe se encarrega de busca-lo.</p>
<p>A classe também segue a sugestão de Mat Buckland e permite a definição de um GlobalState. O GlobalState é processado antes de todos os estados.Alguns exemplos de ações globais são: "Verificar se tem vida, sono, fome, etc".</p>
<p>[sourcecode language="cpp"]<br />
#ifndef STATEMACHINE_H_INCLUDED<br />
#define STATEMACHINE_H_INCLUDED</p>
<p>#include <queue><br />
#include "State.h"</p>
<p>namespace sofia<br />
{<br />
   namespace state<br />
   {<br />
      template <typename EntityType><br />
      class StateMachine<br />
      {<br />
         private:<br />
            EntityType& owner;<br />
            State<EntityType>* globalState;<br />
            State<EntityType>* currentState;<br />
            std::queue<EntityType*> previousStates;</p>
<p>            void doTheChange(State<EntityType>* nextState)<br />
            {<br />
               currentState->leave(*this);<br />
               currentState = nextState;<br />
               nextState->enter(*this);<br />
            }</p>
<p>         public:<br />
            StateMachine(EntityType& _owner,<br />
                State<EntityType>* _globalState,<br />
                State<EntityType*> _currentState)<br />
            : owner(_owner), globalState(_globalState), currentState(_currentState)<br />
            {<br />
            }</p>
<p>            EntityType& getOwner() const<br />
            {<br />
               return owner;<br />
            }</p>
<p>            void dropToState(State<EntityType>* nextState)<br />
            {<br />
               assert(nextState != NULL);<br />
               previousStates.clear();<br />
               doTheChange(nextState);<br />
            }</p>
<p>            void changeState(State<EntityType>* nextState)<br />
            {<br />
               assert(nextState != NULL);<br />
               previousStates.push(currentState);<br />
               doTheChange(nextState);<br />
            }</p>
<p>            void changeGlobalState(State<EntityType>* nextGlobalState)<br />
            {<br />
               globalState->leave(*this);<br />
               globalState = nextGlobalState;<br />
            }</p>
<p>            bool rewindState()<br />
            {<br />
               assert(!previousStates.isEmpty());</p>
<p>               doTheChange(previousStates->front());<br />
               previousStates.pop();</p>
<p>               return !previousStates.isEmpty();<br />
            }</p>
<p>            void process()<br />
            {<br />
               if (globalState != NULL)<br />
                  globalState->process();<br />
               if (currentState != NULL)<br />
                  currentState->process();<br />
            }</p>
<p>            bool isInState(const State<EntityType*>& state) const<br />
            {<br />
               return currentState == state;<br />
            }</p>
<p>            State<EntityType>* getCurrentState() const<br />
            {<br />
               return currentState;<br />
            }</p>
<p>            State<EntityType>* getPreviousState() const<br />
            {<br />
               return previousStates.front();<br />
            }<br />
      };<br />
   }<br />
}</p>
<p>#endif // STATEMACHINE_H_INCLUDED<br />
[/sourcecode]</p>
<p>Um estado, dentro desse contexto é uma interface bastante simples. Não vi muitas vantagens em modela-lo integralmente como um template. Aliás, parece-me vantagem que ele tenha uma estrutura formal. Se necessário for, pode-se criar um Adapter que receba três functors e mapeiem-nos para essa interface.</p>
<p>[sourcecode language="cpp"]<br />
namespace sofia<br />
{<br />
   namespace state<br />
   {<br />
      template <typename EntityType><br />
      class State<br />
      {<br />
         public:<br />
            virtual void enter(StateMachine<EntityType>& owner) = 0;<br />
            virtual void process(StateMachine<EntityType>& owner) = 0;<br />
            virtual void leave(StateMachine<EntityType>& owner) = 0;<br />
            virtual ~State() {};<br />
      };<br />
   }<br />
}[/sourcecode]</p>
<p>Agora, poderei aplicar essa classe juntamente com os steering behaviors já programador no Bola Gelada, conforme sugeriu o prof. Fábio Binder.</p>
<p>Uma das idéias é também criar uma classe ScriptedState, que automaticamente delega os métodos enter(), leave() e process() para um script, seja ele Lua ou Squirrel.</p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[Substituição]]></title>
<link>http://aifuture.wordpress.com/?p=9</link>
<pubDate>Fri, 11 Jul 2008 19:43:59 +0000</pubDate>
<dc:creator>edersonmelo</dc:creator>
<guid>http://aifuture.wordpress.com/?p=9</guid>
<description><![CDATA[Estava pensando em como poderiamos empregar de forma armoniosa, máquinas e homens. Lembrei então d]]></description>
<content:encoded><![CDATA[<p>Estava pensando em como poderiamos empregar de forma armoniosa, máquinas e homens. Lembrei então das <strong>3 leis da robôtica</strong>:</p>
<p><span style="color:#ffffff;"><em>As Três Leis da Robótica são leis que foram elaboradas pelo escritor Isaac Asimov em seu livro de ficção I, Robot ("Eu, Robô") que dirigem o comportamento dos robôs. São elas:</em></span></p>
<p><span style="color:#ffffff;"><em>* 1ª lei: Um robô não pode ferir um ser humano ou, por omissão, permitir que um ser humano sofra algum mal..<br />
* 2ª lei: Um robô deve obedecer as ordens que lhe sejam dadas por seres humanos, exceto nos casos em que tais ordens contrariem a Primeira Lei.<br />
* 3ª lei: Um robô deve proteger sua própria existência desde que tal proteção não entre em conflito com a Primeira e Segunda Leis. </em></span></p>
<p><span style="color:#ffffff;"><em>O objetivo das leis, segundo o próprio Asimov, era tornar possível a existência de robos inteligentes (as leis pressupõem inteligência suficiente para distinguir o bem do mal) e que não se revoltassem contra o domínio humano. Adicionalmente, ainda segundo o próprio Asimov, as leis lhe deram o mote para um número grande de histórias, baseadas em diferentes interpretações das leis. Quando escreveu <a title="The Robots of Dawn" href="http://pt.wikipedia.org/wiki/The_Robots_of_Dawn">Os Robôs do Amanhecer</a>, Asimov introduziu um Robô, chamado <a class="mw-redirect" title="R. Giskard" href="http://pt.wikipedia.org/wiki/R._Giskard">R. Giskard</a>, que tinha sido de uma menina, filha de um famoso roboticista do planeta <a title="Aurora" href="http://pt.wikipedia.org/wiki/Aurora">Aurora</a>, Dr <a class="new" title="Han Falstolfe (ainda não escrito)" href="http://pt.wikipedia.org/w/index.php?title=Han_Falstolfe&#38;action=edit&#38;redlink=1">Han Falstolfe</a>. Esta menina, a custa de "mexer" no cérebro robótico (como as crianças inteligentes geralmente fazem com seus brinquedos) acabou introduzindo em Giskard características que nem mesmo ela se dava conta. O próprio robô ocultou da menina suas faculdades especiais. É Giskard que mais tarde elabora a lei zero, mas esta lei era só dele, e de <a title="R. Daneel Olivaw" href="http://pt.wikipedia.org/wiki/R._Daneel_Olivaw">R. Daniel</a>, e jamais se tornou de conhecimento público. Esta lei zero foi incorporada por R. Daniel aos robôs que ele mesmo construiu (inclusive uma robô-mulher com quem Seldon viveu).</em></span></p>
<p><span style="color:#ffffff;"><strong><span><em>A 'Lei Zero': </em><em>um robô não pode fazer mal à humanidade e nem, por inacção, permitir que ela sofra algum mal. Desse modo, o bem da humanidade é primordial ao dos indivíduos.</em></span></strong></span></p>
<p><span style="color:#ffffff;"><em>A chamada lei zero, porém, tem o sério problema de transferir ao robô o poder (possibilidade) de avaliar, diante das situações concretas, se o interesse da humanidade se sobrepõe ao interesse individual. Tal possibilidade abre uma perigosa brecha para a ditadura das máquinas, que elegeriam por si qual é o bem maior, sendo-lhe permitido, inclusive, fazer o mal a um ser humano (indivíduo), caso entendam que isso é melhor para a humanidade. Essa ditadura das máquinas é insinuada no último conto de <a class="mw-redirect" title="I, robot" href="http://pt.wikipedia.org/wiki/I%2C_robot">I, robot</a>, "O Conflito Evitável", no qual o Coordenador Mundial (o governador geral das 4 regiões em que a Terra se dividiu após superar as divisões nacionais) entrevista Susan Calvin e chegam a conclusão de que as máquinas aos poucos estão tomando o controle dos destinos do planeta. Segundo o conto, alguns humanos (a Sociedade em Prol da Humanidade) descontentes com o poder que as máquinas passaram a ter, começam a sabotar os sistemas de produção, distribuição e organização da mão-de-obra, para que a culpa da desordem mundial recaísse sobre os robôs. Entretanto, as máquinas começam a fazer um jogo de lógica e influência com a humanidade para, aos poucos, eliminar os revoltosos para o bem geral da resto da população do planeta. Mas isto foi antes da elaboração da lei zero, por Giskard.</em></span></p>
<p>(Fonte: <a href="http://pt.wikipedia.org/wiki/Tr%C3%AAs_Leis_da_Rob%C3%B3tica" target="_blank">Wikipédia</a>)</p>
<p>Máquinas produzidas no sentido de raciocinar precisariam de um cérebro capaz de entender, agir, reagir, <strong>"raciocinar"</strong>. Percebam que chegamos a como tudo ocorre.</p>
<p><strong>Raciocínio</strong>, e não estou falando que ele TENHA quer ser lógico, nós não somos. Consequimos suprimir a lógica de um fato <a href="http://pt.wiktionary.org/wiki/irrefut%C3%A1vel" target="_blank">irrefutável </a>em prol de um amor, de uma lembrança, de um ideal, por mais absurdo que ele seja.</p>
<p>Então para que criar máquinas lógicas?  Para que possamos controlar e utilizar de forma inadequada!?</p>
<p>Mas acabamos caindo em outro abismo chamado <a href="http://pt.wikipedia.org/wiki/Livre-arb%C3%ADtrio" target="_blank"><strong>LIVRE ARBÍTRIO</strong></a> que estariamos dando para estas máquinas.<br />
Isso chama-se <strong>substituição.</strong> Criamos outro ser capaz de consciência, raciocínio, amor. E estaremos substituindo a <strong>raça humana</strong> pela <strong>raça superhumana</strong>. Começando a criar  um <strong>Ser</strong> de forma inadeguada. Fora da ordem natural da evolução animal, fora da ordem cronológica do homen e da natureza.</p>
<p>Poderiamos estar começando uma nova raça para substituir a nossa.</p>
<p>Mesmo assim, acredito, por enquanto, <em>estar a favor da criação de uma máquina que seja capaz.</em></p>
<p><em>Abraço,<br />
Ederson Melo </em></p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[Desenvolvendo inteligência artificial altamente qualificada.]]></title>
<link>http://ocamaradinha.wordpress.com/?p=68</link>
<pubDate>Fri, 11 Jul 2008 18:09:00 +0000</pubDate>
<dc:creator>ocamaradinha</dc:creator>
<guid>http://ocamaradinha.wordpress.com/?p=68</guid>
<description><![CDATA[Já estamos perto do momento no qual novos tipos de rotinas automatizadas e programas de computador ]]></description>
<content:encoded><![CDATA[<p>Já estamos perto do momento no qual novos tipos de rotinas automatizadas e programas de computador poderão operar independentemente do controle humano direto, para desempenhar tarefas pré-definidas. Ajudando a alcançar esse objetivo, pesquisadores desenvolveram um modelo que auxilia o desenvolvimento de aplicações construídas a partir de objetos móveis capazes de ter noção de si próprios, ou sensientes.</p>
<p>Antes de mais nada, os programadores precisam vencer as limitações das arquiteturas e das camadas intermediárias atuais, largamente baseadas em modelos de programação seqüenciais. Este é o objetivo do programa de pesquisas europeu CORTEX, que planeja também explorar as questões teóricas fundamentais e as questões práticas relacionadas ao uso de "objetos sensientes". "De um lado nós temos os sistemas clássicos de controle, programados em um formato estritamente seqüencial, para responder a uma seqüência precisamente definida de eventos," explica o coordenador do projeto Paulo Veríssimo, da Universidade de Lisboa.</p>
<p>"De outro lado, nós temos o mundo real, onde os ambientes interagem e pouca coisa pode ser prevista com precisão. Se desejamos construir coisas altamente interativas, como robôs móveis, equipamentos de vestir que possam interagir de forma inteligente com seu ambiente, sistemas de realidade ampliada, etc., nós precisamos saber como programar essas aplicações."</p>
<p>Os pesquisadores já criaram um modelo de programação para apoiar o desenvolvimento de aplicações móveis sensientes, ou conscientes de si mesmas. Eles criaram uma arquitetura de sistemas aberta e escalável que permite o mapeamento de vários tipos de redes, de redes CAN até LANs e WANs, especialmente aquelas que utilizam tecnologias de comunicações móveis. Eles também prototiparam a camada intermediária necessária para suportar o modelo, que garante o funcionamento dos protocolos e serviços necessários ao funcionamento dos objetos sensientes.</p>
<p>Para apresentar os resultados da pesquisa, os cientistas desenvolveram vários protótipos de demonstração, incluindo um que mostra como dispositivos robóticos podem assinar e cancelar a assinatura em listas de distribuição de <a href="http://www.inovacaotecnologica.com.br/noticias/noticia.php?artigo=010150051117#">informações</a>, tanto como provedores de informação quanto como usuários da informação.</p>
<p>De forma geral, robôs móveis individuais são incapazes de avaliar o ambiente ao seu redor simplesmente a partir dos seus próprios sensores - eles precisam cooperar com outros. Na demonstração, um sistema supervisor externo monitorava suas ações e mostrava como a base de conhecimentos de cada robô individual se expande por meio da cooperação com outros.</p>
<p><img src="http://www.inovacaotecnologica.com.br/noticias/imagens/010150051117-sensientes_2.jpg" alt="Passando dos programas passivos para aplicações sensientes" align="left" /></p>
<p>A demonstração de cooperação entre automóveis mostrou como os carros podem comunicar-se uns com os outros e reagirem aos movimentos dos demais para evitar acidentes. Os pesquisadores montaram um simulador de cruzamento, com uma série de carros se aproximando a diferentes velocidades. Permitindo que os veículos se comunicassem uns com os outros, utilizando conexões sem fios, todos passaram pelo cruzamento em um fluxo contínuo, sem que nenhum precisasse parar, simplesmente ajustando suavemente suas velocidades à medida em que se aproximavam da esquina. A mesma técnica pode ser aplicada para trens, aviões e qualquer outra forma de transporte, segundo Veríssimo.</p>
<p>A fim de testar perfeitamente sistemas críticos quanto à segurança, é normalmente necessário construir e testar as ações dos equipamentos prontos, assim como testar o software. Entretanto, em muitas aplicações em larga escala, como veículos se aproximando de um cruzamento, por exemplo, esses testes podem não apenas ter um custo proibitivo, como também ser muito perigosos.</p>
<p>Para resolver esse problema, os cientistas desenvolveram e demonstraram uma plataforma de software para emular ambientes reais para o testes de aplicações relacionadas à segurança. A plataforma foi projetada especificamente para complementar metodologias tradicionais de engenharia de software, tais como métodos formais para a especificação, desenvolvimento e verificação de redundância em sistemas de hardware e software.</p>
<p>"Nós demos sensibilidade ao contexto a essas aplicações, capacitando-as a entender o que está acontecendo nas suas imediações. Por exemplo, um robô que possa ir a uma área de acidente sem conhecimento anterior daárea e de suas cercanias," explica Veríssimo. "Aplicações como esta são capazes de cooperar para analisar autonomamente seu ambiente, e reagir conforme a necessidade."</p>
<p>O projeto CORTEX chamou a atenção de várias empresas. Seus resultados estão agora servindo como ponto de partida para uma nova etapa de pesquisas mais práticas, quando os pesquisadores já trabalharão diretamente com parceiros da indústria para o desenvolvimento de produtos finais, que poderão chegar ao mercado.</p>
<p>FONTE: www.inovacaotecnologica.com.br</p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[Duas novidades sobre o Blog]]></title>
<link>http://edersonmelo.wordpress.com/?p=27</link>
<pubDate>Fri, 11 Jul 2008 17:07:55 +0000</pubDate>
<dc:creator>edersonmelo</dc:creator>
<guid>http://edersonmelo.wordpress.com/?p=27</guid>
<description><![CDATA[Voltando com novidades como antes informado. 
A primeira novidade 
Para separar um assunto que gosto]]></description>
<content:encoded><![CDATA[<p><em><strong>Voltando com novidades como antes informado. </strong></em></p>
<p><strong><em>A primeira novidade </em></strong><br />
Para separar um assunto que gosto de discutir e manter ele de forma dedicada, criei um<em> <a href="http://aifuture.wordpress.com/" target="_blank">blog novo</a></em> sobre Inteligência Artificial e Física.</p>
<p>Não sou e nem numca serei um especialista nas duas áreas, mas gosto de discutir a parte filosófica da coisa. Caso queiram conferir <a href="http://aifuture.wordpress.com/" target="_blank">aifuture.worpress.com</a>.</p>
<p><em><strong>O <a href="http://aifuture.wordpress.com/" target="_blank">aifuture.worpress.com</a> contará com posts a cada 3 dias, devido a outros compromissos.</strong></em></p>
<p><strong><em>A segunda novidade</em></strong><br />
Este blog contará(como sempre digo, pretendo que seja assim), com posts a <strong><em>cada dois dias</em></strong>.</p>
<p><em>Abraço,<br />
Ederson Melo </em></p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[Robots y el hombre]]></title>
<link>http://bluelennon.wordpress.com/?p=443</link>
<pubDate>Fri, 11 Jul 2008 15:41:39 +0000</pubDate>
<dc:creator>Spideymang</dc:creator>
<guid>http://bluelennon.wordpress.com/?p=443</guid>
<description><![CDATA[Cada vez, el humano está más cerca de lograr el sueño de realizar un robot muy semejante a él. E]]></description>
<content:encoded><![CDATA[<p>Cada vez, el humano está más cerca de lograr el sueño de realizar un robot muy semejante a él. En las películas de ciencia ficción nos muestran algunos diseños muy interesantes, veamos:</p>
<p><span style="font-weight:bold;">El Hombre Bicentenario</span>.<br />
En esta película nos muestran un posible futuro [no muy lejano] donde un androide es el protagonista de la historia y que al principio de la película es comprado por una familia para ocuparlo en sencillas tareas del hogar.</p>
<p style="text-align:center;"><img class="alignnone" src="http://i76.photobucket.com/albums/j39/zooboorex/19035.jpg" alt="" width="164" height="233" /></p>
<p style="text-align:left;"><span style="font-weight:bold;">Yo Robot</span>.<br />
<span>La historia se desarrolla en el año 2035, en el cual los robots son un ítem y los humanos los usan a diario, tanto que les tienen una gran confianza. Entre sus ventajas, estos robots humanoides tienen un software que se actualiza inalambricamente.</span>
</p>
<p style="text-align:center;"><img class="aligncenter" src="http://i76.photobucket.com/albums/j39/zooboorex/yo_robot.jpg" border="0" alt="" hspace="0" vspace="0" width="184" height="225" align="bottom" /></p>
<p style="text-align:left;"><span style="font-weight:bold;">Inteligencia Artificial</span>.</p>
<div style="text-align:justify;">La historia básicamente esta adaptada en la época en la que los recursos naturales son limitados y la tecnología está avanzando a un ritmo vertiginoso. Los alimentos están creados por ingeniería y hay un robot para todas las necesidades, excepto el amor. La emoción es la última y controvertida frontera en la evolución de los robots pero Cybertronics Manufacturing ha creado la solución. Se trata de David, el primer niño robótico programado para amar que es adoptado a modo de prueba por un empleado de Cybertronics y su esposa, cuyo hijo, que tiene una enfermedad terminal .</div>
<p style="text-align:center;"><img class="aligncenter" src="http://i76.photobucket.com/albums/j39/zooboorex/ai_movie_copy_rescale.jpg" border="0" alt="" hspace="0" vspace="0" align="bottom" /></p>
<p style="text-align:left;">Después de estos ejemplos, entramos en materia y ahora les pongo la imagen de un robot capaz de expresar emociones con gestos que reproduce moviendo su cara, muy similar al robot de la última película mencionada.</p>
<p style="text-align:left;"><strong><span style="font-weight:normal;">Se llama </span>Nexi</strong>, y fue creado por el <a href="http://www.mit.edu/" target="_blank">MIT</a> (Massachussets Institute of Technology, Estados Unidos), puede encuadrarse en la categoría de robots humaniodes sociales, esto es, robots cuyo aspecto se asemeja al nuestro, y que además poseen ciertas habilidades para interactuar con las personas. Posee varios motores en la cara, manos y cuerpo que hacen que sea capaz de imitar el comportamiento de los seres humanos y así expresar emociones de una forma muy humana.</p>
<p style="text-align:center;"><img src="http://i76.photobucket.com/albums/j39/zooboorex/nexi-robot.jpg" border="0" alt="" hspace="0" vspace="0" width="195" height="162" align="bottom" /></p>
<p style="text-align:left;">El robot tiene el tamaño de un niño de tres años, es capaz de levantar 4 kilogramos y medio de peso y posee movimiento autónomo, una cámara en color en cada ojo, y una de infrarrojos en el centro de su frente para poder detectar posiciones en 3D (la tecnología de infrarrojos le permite conocer la distancia a los objetos que ve) y poder crear mapas 3D para navegar con sus cuatro ruedas que le permiten moverse por el entorno. Además posee cuatro micrófonos para detectar de dónde vienen los sonidos.</p>
<p>Y <span style="font-weight:bold;">si lo quieren ver en acción </span>aquí les dejo el <a href="http://www.youtube.com/watch?v=EwLJ60xVwgU" target="_blank">vídeo.</a></p>
<p>Como vemos, la tecnología va dando pasos agigantados, primero el proyecto del robot <a href="http://world.honda.com/ASIMO/" target="_blank">ASIMO</a> de Honda y ahora el robot emocional...</p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[Redes Neurais]]></title>
<link>http://aifuture.wordpress.com/?p=5</link>
<pubDate>Wed, 09 Jul 2008 13:22:20 +0000</pubDate>
<dc:creator>edersonmelo</dc:creator>
<guid>http://aifuture.wordpress.com/?p=5</guid>
<description><![CDATA[Redes neurais, ou, mais propriamente Redes neuronais artificiais, são sistemas computacionais basea]]></description>
<content:encoded><![CDATA[<p>Redes neurais, ou, mais propriamente Redes neuronais artificiais, são sistemas computacionais baseados numa aproximação à computação baseada em ligações. Nós simples (ou "<a href="http://pt.wikipedia.org/wiki/Neur%C3%B4nio" target="_blank">neurões</a>", "<a href="http://pt.wikipedia.org/wiki/Neur%C3%B4nio" target="_blank">neurônios</a>", "processadores" ou "unidades") são interligados para formar uma rede de nós - daí o termo "rede neuronal". A inspiração original para esta técnica advém do exame das estruturas do <a href="http://pt.wikipedia.org/wiki/C%C3%A9rebro" target="_blank">cérebro</a>, em particular do exame de <a href="http://pt.wikipedia.org/wiki/Neur%C3%B4nio" target="_blank">neurônios</a>.</p>
<p>No campo da inteligência artificial da informática, Redes Neurais Artificiais (RNA), são sistemas não lineares que imitam o mecanismo de processamento do <a href="http://pt.wikipedia.org/wiki/C%C3%A9rebro_humano" target="_blank">cérebro humano</a>.</p>
<p>As primeiras informações sobre neurocomputação surgiram em 1943, em artigos de um neurofisiologista chamado Warren McCulloch, do MIT, e pelo matemático Walter Pitts da Universidade de Illinois, onde fizeram uma analogia entre células nervosas vivas e o processo eletrônico em um trabalho publicado sobre "neurônios formais", simulando o comportamento do neurônio natural, onde o neurônio possuía apenas uma saída, que era uma função da soma de valor de suas diversas entradas. O trabalho consistia num modelo de resistores variáveis e amplificadores representando conexões sinápticas de um neurônio biológico.</p>
<p>As redes neurais artificiais são um método para solucionar problemas através da simulação do cérebro humano, inclusive em seu comportamento, ou seja, aprendendo, errando e fazendo descobertas. São técnicas computacionais que apresentam um modelo inspirado na estrutura neural de organismos inteligentes e que adquirem conhecimento através da experiência.</p>
<p>As redes neurais possuem nós ou unidades de processamento. Cada unidade possui links para outras unidades, no qual recebem e enviam sinais. Cada unidade pode possuir memória local.</p>
<p>Estas unidades são a simulação dos neurônios, recebendo e retransmitindo informações. Soma-se as entradas e retorna uma saída, caso esta seja maior que o valor da soma.</p>
<p>Um rede neural pode possuir uma ou múltiplas camadas. Exemplificando com três camadas, poderíamos ter a camada de entrada, onde as unidades recebem os padrões, a camada intermediária, onde é feito processamento e a extração de características, e a camada de saída que conclui e apresenta o resultado final. Quanto maior o número de camadas, melhor a capacidade de aprendizado. A camada de entrada deve possuir uma unidade especial conhecida como "bias", que serve para aumentar</p>
<p>Em termos mais técnicos, o número de camadas define a capacidade de representação das relações entre o espaço de entrada e de saída. A inexistência da camada intermediária, característica do modelo Perceptrons, condiciona-o a representar bem somente relações linearmente independentes. A existência de camadas intermediárias, característica do modelo Perceptron de Múltipla Camada (MLP), retira tal limitação. Se houver apenas uma camada intermediária, o MLP pode representar (com qualquer grau de aproximação, por menor que seja...) qualquer função contínua. Duas ou mais camadas, ampliam o universo de representação a qualquer função contínua ou não.</p>
<p>Redes Neurais Artificiais, seguindo a tradição norte-americana, estão muito associadas à adaptação de conexões (sinapses) entre neurônios, ao Conexionismo. Cabe registrar, entretanto, a existência de modelos onde as conexões não são adaptadas, mas, sim, apenas transmitem estimulação entre neurônios. Tais modelos são chamados Redes Neurais Sem Pesos (do Inglês, Weightless Neural Networks). Para completar, há modelos onde as sinapses não são adaptadas, mas calculadas previamente, servindo a tarefas de otimização geralmente.</p>
<p><strong>Diferenciação</strong></p>
<p>Hoje em dia a maior parte dos investigadores concorda que as redes neuronais são muito diferentes do cérebro em termos de estrutura. No entanto, como o cérebro, uma rede neuronal é uma coleção massivamente paralela de unidades de processamento pequenas e simples, onde as interligações formam a maior parte da inteligência da rede. Entretanto, em termos de escala, o cérebro é muito maior que qualquer rede neural. Além disso, as unidades usadas na rede neural são tipicamente muito mais simples que os neurônios e o processo de aprendizado do cérebro (embora ainda desconhecido) é, certamente, muito diferente do das redes neurais.<br />
<strong><br />
Rede Pró-alimentada</strong></p>
<p>Uma rede neural "pró-alimentada" (em contraposição a "retroalimentada") típica consiste de um conjunto de nós. Alguns desses nós são designados nós de entrada, outros nós de saída e aqueles que estão entre estes dois tipos de nós são chamados de nós "escondidos". Existem também conexões entre os neurônios, com um número referido como um ponderador associado a cada conexão. Quando a rede está em operação, um valor de entrada será aplicado a cada nó de entrada - estes valores são colocados por um operador humano ou por sensores ambientais ou talvez por outros programas. Cada nó então passa seu dado valor para as conexões que saem dele e em cada conexão o valor é multiplicado por um ponderador associado a essa conexão. Cada nó na camada seguinte então recebe um valor que é a soma dos valores produzidos pelas conexões que chegam até ele e em cada nó é realizada uma computação simples sobre esse valor - uma função sigmóide é típica. O processo então é repetido com os resultados sendo passados através de camadas subsequentes de nós até que os nós de resultados sejam atingidos.</p>
<p><em><strong>Nota: isto é baseado em um modelo de neurônio da década de 1970.</strong></em></p>
<p>Os modelos alternativos de cálculo nas redes neurais incluem aqueles dotados de "loops" (nos quais algum tipo de processo de retardamento de tempo precisa ser usado) e os modelos "o vencedor leva tudo", nos quais o neurônio com os valores mais altos "dispara" e toma o valor 1, e todos os outros neurônios tomam o valor 0.</p>
<p>Tipicamente os ponderadores em uma rede neural são colocados inicialmente em valores aleatórios pequenos; isto significa que a rede não sabe nada. À medida que o processo de treinamento acontece, esses ponderadores irão convergir para valores que permitem que eles realizem uma computação útil. Assim pode ser dito que uma rede neural começa sabendo nada e move-se no sentido de ganhar algum conhecimento real.</p>
<p>As redes neurais são particularmente úteis para lidar com dados ligados a valores reais em que se deseja obter uma saída dotada de valor real; desta maneira as redes neurais irão realizar uma classificação por graus, e serão capazes de expressar valores equivalentes a "não conhecido com certeza". Se uma rede neural é treinada usando a função de erro de entropia cruzada (veja o livro de Bishop) e se a saída dessa rede neural tem uma forma sigmoidal não-linear, então as saídas serão estimativas de uma probabilidade posterior real de uma classe.</p>
<p><strong>Aplicações reais</strong></p>
<p>Em aplicações reais, as redes neurais se saem particularmente bem nas seguintes tarefas:</p>
<p>* Aproximação de funções;<br />
* Previsão de séries temporais;<br />
* Classificações;<br />
* Reconhecimento de Padrões.</p>
<p><strong>CTRNN</strong></p>
<p>Outros tipos de redes neurais, em particular Redes Neurais Recorrentes de Tempo Contínuo (Continuous-Time Recurrent Neural Networks - CTRNN), são usadas em conjunto com Algoritmos Genéticos (Genetic Algorithms - GAs) para produzir controladores robóticos. O genoma é então constituído dos parametros de rede e, a aptidão de uma rede é a adequação do comportamento exibido pelo robô controlado (ou freqüentemente por uma simulação deste comportamento).</p>
<p>Tipos de Redes Neurais</p>
<p>O exemplo mais antigo de redes neurais são as redes perceptron com uma camada de nós de saída, conectados às entradas por conjuntos de pesos. Esta topologia pode ser considerada a forma mais simples de rede em avanço. A soma do produtos dos pesos pelas entradas é calculada por cada nó de saída, e se o valor calculado ultrapassar um certo limiar (geralmente 0), o neurônio dispara e ajusta a saída para o valor 1; se o valor calculado é menor que o limiar, a saída é ajustada para o valor -1. Ao mesmo tempo, um algoritmo de aprendizado calcula a diferença entre a saída calculada e os dados de entrada, e usa o valor da diferença para ajustar os pesos da rede.</p>
<p><strong>Perceptron com uma Camada</strong></p>
<p>Redes perceptron com uma camada são o tipo mais antigo de redes neurais, as quais são formadas por uma camada única de neurônios de saída, os quais estão conectados por pesos às entradas. Este é o exemplo mais simples de redes em avanço. A soma do produto entre pesos e entradas alimenta cada neurônio de saída, e se o resultado desta operação exceder um certo limiar (geralmente 0), o neurônio coloca o valor 1 na saída; se o resultado for inferior ao limiar, o neurônio coloca o valor -1 na saída. Neurônios com esse comportamento são chamados de neurônios de McCulloch-Pitts ou neurônios com limiar. Na literatura técnica o termo perceptron diz respeito a redes com apenas um desses neurônios.</p>
<p>Perceptrons podem ser treinados por um algoritmo de aprendizagem simples, chamado geralmente de regra-delta. Este algoritmo calcula os erros entre a saída dos dados calculados e a saída desejada, e utiliza isso para ajustar os pesos, assim executando um formulário da descida do gradiente.</p>
<p>Os perceptrons de uma camada são capazes de aprender somente sobre problemas linearmente separáveis (que podem ser separados por uma reta em uma hiperplano; em 1969 em uma monografia famosa intitulada Perceptrons por Marvin Minsky e por Seymour Papert mostrou que era impossível para uma única rede do perceptron da camada aprender uma função de XOR, Conjecturou (incorretamente) que um resultado similar penderia para uma rede multi-camadas do perceptron. Embora uma única unidade do ponto inicial fosse completamente limitada em seu poder computacional, mostrou-se que as redes de unidades paralelas do ponto inicial podem aproximar toda a função contínua de um intervalo compacto dos números reais no intervalo [ - 1, 1 ]. Este resultado muito recente pode ser encontrado em [ Auer, Burgsteiner, Maass: A regra de aprendizagem para perceptrons paralelos, 2001 do p-delta (estado janeiro 2003: submetido para a publicação) ].</p>
<p><strong>Perceptron Multi-camadas</strong></p>
<p>Esta classe de rede consiste de múltiplas camadas de unidades computacionais, geralmente interconectadas em uma forma feedforward. Isso quer dizer que cada neurônio em uma camada tem conexões diretas a neurônios da próxima camada. Em muitas aplicações as unidades dessas redes aplicam uma função sigmóide (em forma de S) como a função de ativação..</p>
<p>O teorema de aproximação universal dita que toda função contínua que mapeia intervalos de números reais a algum intervalo de números reais de saída pode ser arbitrariamente aproximado com precisão por um perceptron multi-camadas com somente uma camada oculta. Este resultado só é válido para classes restritas de funções de ativação, por exemplo funções sigmóides.</p>
<p>Redes Multi-camadas podem usar um grande número de técnicas de aprendizado, sendo que a mais popular é a propagação reversa. Neste caso os valores de saída são comparados com a resposta correta para computar o valor de alguma função-erro predefinida. Por alguma técnica o erro é então alimentado de volta na rede. Usando essa informação, o algoritmo ajusta os pesos de cada conexão para reduzir o valor da função erro. Apos repetir este processo por um número suficiente.</p>
<p><strong>Fonte:</strong> <a href="http://pt.wikipedia.org/wiki/Redes_Neurais" target="_blank">Wikipédia</a> (Salvo alterações pessoais feitas no texto para meu blog)</p>
<p><em>Abraço,<br />
Ederson Melo </em></p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[Inteligência Artificial]]></title>
<link>http://paginasdefilosofia.wordpress.com/?p=181</link>
<pubDate>Sun, 06 Jul 2008 21:39:54 +0000</pubDate>
<dc:creator>Páginas de Filosofia</dc:creator>
<guid>http://paginasdefilosofia.wordpress.com/?p=181</guid>
<description><![CDATA[AI  RESEARCHER JOB  OFFER CALL at UNL, Portugal
(Open till 31 August 0 
Applications are invited for]]></description>
<content:encoded><![CDATA[<p>AI  RESEARCHER JOB  OFFER CALL at UNL, Portugal<br />
(Open till 31 August 08)<br />
Applications are invited for a RESEARCHER position (at least 3 years post-doctoral experience) in thematic areas of Artificial Intelligence.<br />
These positions offered are for a 5-year contract to work at our research institution, in the Lisbon area. In exceptional cases, duly justified, we may consider applicants with less than 3 years of post-doctoral experience. See http://alfa.fct.mctes.pt/apoios/contratacaodoutorados/edital2008 for further information.<br />
Any candidate must have a strong Computer Science background, and be knowledgeable in one or more of these areas (order irrelevant):<br />
Semantic Web; Knowledge Representation and Reasoning; Autonomous Agents and Multi-Agent Systems; Logic Programming; Machine Learning and Data Mining; Constraint Programming and Optimisation; Simulation (including artificial life); Bioinformatics; Cognitive Science; Ambient Intelligence; Computational Processing of Written Natural Language (Portuguese); Planning; Intelligent Information Systems; or other Artificial Intelligence areas.<br />
In addition to their integration in the research Centre for Artificial Intelligence <a href="http://centria.di.fct.unl.pt" target="_blank">(CENTRIA</a>), the candidates are expected to help with post-graduate teaching, including the supervision of post-graduate students, to write research papers as well as project and grant applications, and be able to interact with scientists within and outside the host Institution.<br />
Candidates will profit from the technical facilities and expertise available at CENTRIA, at the Faculdade de Ciências e Tecnologia, Universidade Nova de Lisboa, where they will be stationed.<br />
The salary is about 3.101 €/month, 14 months a year, before 35% tax retention. The contract includes social benefits and retirement fund.<br />
Please send by email letter of intent, detailed curriculum vitae, and at most two reference letters to:</p>
<p>Prof. Luís Moniz Pereira                                   lmp@di.fct.unl.pt<br />
Director<br />
Centro de Inteligência Artificial<br />
Universidade Nova de Lisboa<br />
Quinta da Torre<br />
2825-516 Caparica<br />
Portugal</p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[La verdadera computadora del futuro (nada de basura intel, dell, etc), cómo la ves?]]></title>
<link>http://arukard.wordpress.com/?p=205</link>
<pubDate>Fri, 04 Jul 2008 22:46:22 +0000</pubDate>
<dc:creator>arukard</dc:creator>
<guid>http://arukard.wordpress.com/?p=205</guid>
<description><![CDATA[Estoy aburrido y cansado de escuchar falsos diseños de computadoras futuristas expuestos por quiene]]></description>
<content:encoded><![CDATA[<p>Estoy aburrido y cansado de escuchar falsos diseños de computadoras futuristas expuestos por quienes producen computadoras o sistemas operativos, son de lo peor, lo mismo de siempre, cajones gigantes como siempre o pantallas diminutas, acá un concepto interesante propuesto por varias personas:</p>
<p><strong>Un anillo que sirve de computadora portatil, con las siguientes características:</strong></p>
<p>Peso: 20 gramos.</p>
<p>Color: Negro, blanco, dorado, pasteles, etc.</p>
<p><a href="http://es.wikipedia.org/wiki/Gema">Gema</a>: Imitación de diamante, hematita, pirita, esmeralda, perla, agata azul, zafiro, jade, ojo de tigre, etc.</p>
<p>1.- Monitor holográfico incorporado en la gema en dos versiones:</p>
<p>- Monitor 2d a 50 pulgadas con 2000 lúmenes.</p>
<p>- Monitor 3d, representa los cuerpos humanos en tamaño real, cuesta 100 euros mas.<br />
Es un laser que sale de donde va la gema en los anillos tradicionales, con estabilizador de imágen para que aunque uno se mueva la imágen se mantenga en el mismo sitio.</p>
<p>2.- Disco duro a 10 TB (para el 2015 a 20 TB).</p>
<p>3.- Reconocimiento y dictado por voz.</p>
<p>4.- Mouse adaptado en la uña del dedo índice.</p>
<p>5.- Sistema operativo auxiliado por alice (inteligencia artificial), lo que evita que tengas que escribir o incluso leer, es tu asistente personal, casi una secretaria(o).<br />
6.- No trae drivers, los crea inmediatamente detectando el hardware de forma inhalambricamente por bluetooth o wi-fi, con chip wifi incorporado, tambien crea drivers para aparatos conectados a internet o redes lan.</p>
<p>7.- Cámara web a 30 megapixeles del lado anterior en la gema y con capacidad de generar imágenes 3d.</p>
<p>8.- Micrófono 3d a 7 canales, además de elegir y conectarse automáticamente a los equipos de sonido a 1 kilómetro a la redonda, tambien con audio stadium.</p>
<p>9.- Procesador cuántico (150 qbits) a 50 teraflops.</p>
<p>10.- Teclado laser con tamaño similar a los analógicos, debajo del area de pantalla laser, proyectado cerca del usuario.</p>
<p>11.- Autonomía de la bateria: Una semana, con conector inhalámbrico 110/220 watts para recargar la computadora cuando se esté por terminar la bateria.</p>
<p>12.- Sistema Operativo: Núcleo linux, con opcion de instalar cualquier distro libre contenida en el disco duro de la máquina, alice te pregunta cual distro quieres instalar al encender la computadora.</p>
<p>Esta es la versión portátil, la versión cacera estará en los bombillos de cada cuarto y sumergirá al usuario en un mundo 3d totalmente diferente por radiaciones que la conectan directamente al/los cerebros, pudiendo sumergir literalmente al usuario en internet para interactuar con otros con el avatar que prefiera.</p>
<p>Qué cambios le harias al diseño?<br />
Qué le agregarían o le Quitarían????</p>
<p><strong>Extra: Crea tu propio holograma a colores en 3d - Facilísimo</strong></p>
<p>Consigue o compra una jeringa vacia cualquiera de 5 cc o 10 cc (quitale la aguja y botala), carga la jeringa de agua.</p>
<p>Preferiblemente en un lugar donde hay sol y sombra (puede ser cerca de una pared) al medio dia o por la tarde, presionas la punta de la jeringa para que el agua salga con presión y en gotas muy finas, presiona el otro extremo para que salga el agua, verás que donde cae el agua se forman uno o varios arcoíris multicolores de unos 20 pulgadas de tamaño. (Funciona igual con las máquinas que riegan césped).</p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[Vi-Clone convierte la web de las empresas en una poderosa herramienta de marketing online]]></title>
<link>http://b2boss.wordpress.com/?p=53</link>
<pubDate>Fri, 04 Jul 2008 18:10:16 +0000</pubDate>
<dc:creator>b2boss</dc:creator>
<guid>http://b2boss.wordpress.com/?p=53</guid>
<description><![CDATA[
Este asistente virtual está revolucionando el sistema clásico de atención al cliente

En un mund]]></description>
<content:encoded><![CDATA[<h1></h1>
<p><strong>Este asistente virtual está revolucionando el sistema clásico de atención al cliente</strong></p>
<p><strong></strong><br />
En un mundo empresarial basado en la competitividad, en el que lo más importante es aumentar los beneficios de la compañía año tras año y vender sin parar, ser diferente de los demás puede suponer ganar un elemento estratégico y servir para ampliar la cartera de clientes. La empresa <strong>Vi-Clone Corp</strong>. ha logrado</p>
<p>diseñar una tecnología basada en inteligencia artificial que supone disponer de un asistente virtual llamado <strong>Vi-Clone</strong>, que sin duda dota la empresa de una innovación tecnológica sin precedentes.<a href="http://b2boss.files.wordpress.com/2008/07/1493-2008-07-03.jpg"></a></p>
<p style="text-align:center;"><img class="size-medium wp-image-54 aligncenter" src="http://b2boss.wordpress.com/files/2008/07/1493-2008-07-03.jpg?w=200" alt="" width="200" height="200" /></p>
<p style="text-align:center;">
<p style="text-align:left;"><strong>Las ventajas de un Vi-Clone son numerosas</strong>. Y es que disponer de una de esas máquinas supone un aumento claro de la satisfacción del cliente –ya que éste se siente atendido cuando él lo desea y en el lugar que necesita- y esto tiene consecuencias directas en el número de ventas de la empresa. La otra parte implicada también sale beneficiada de la utilización de Vi-Clone: simplificación de la navegación por la red, obtención inmediata de la información y disponibilidad del servicio a cualquier hora del día..</p>
<p>En palabras de <strong>Rudy Bianco</strong>, CEO y Fundador de Vi-Clone “Nuestra tecnología se basa en darle un valor añadido a la web de las empresas, ofreciéndoles un dependiente que aparece cuando el usuario entra en la página web de la empresa en cuestión. El asistente le hablará, ofreciéndose a ayudarle en cualquier cosa que necesite. Además tiene apariencia humana, y permite la interacción en lenguaje natural, cosa que elimina por completo la incómoda sensación de estar hablando con una máquina. En resumen: un Vi-Clone es una persona metida dentro de un ordenador. Una <strong>potente herramienta de marketing online</strong>.” Las formas clásicas de atención al cliente –correo electrónico, preguntas frecuentes, atención telefónica con horarios restringidos,…- suponen un coste monetario y una pérdida de tiempo para una persona que desea resolver una duda, con el añadido de que la respuesta puede que no le sea proporcionada inmediatamente.</p>
<p style="text-align:left;">
<p style="text-align:left;"><span style='text-align:center; display: block;'><object width='425' height='350'><param name='movie' value='http://www.youtube.com/v/ZkcpqFAf35w'></param><param name='wmode' value='transparent'></param><embed src='http://www.youtube.com/v/ZkcpqFAf35w&rel=0' type='application/x-shockwave-flash' wmode='transparent' width='425' height='350'></embed></object></span><span style='text-align:center; display: block;'><object width='425' height='350'><param name='movie' value='http://www.youtube.com/v/kyg9Ai-MevM'></param><param name='wmode' value='transparent'></param><embed src='http://www.youtube.com/v/kyg9Ai-MevM&rel=0' type='application/x-shockwave-flash' wmode='transparent' width='425' height='350'></embed></object></span></p>
<p style="text-align:left;">
<p style="text-align:left;">Vi-Clone es un todo en uno, es una tecnología permite múltiples aplicaciones de forma instantánea: el dependiente perfecto: comercial, guía, punto de información, buscador,…Por dar unos datos hay que señalar que con uno solo de esos asistentes se es capaz de atender a 1 millón de personas al mismo tiempo, y hablar 17 idiomas diferentes y, lo más importante, las 24 horas del día los 365 días del año. Otra de las grandes ventajas que supone es su capacidad de memorizar la información que proporcionó la última vez que un determinado usuario ‘habló’ con él.</p>
<p>En este contexto diferentes empresas del estado español ya cuentan con un asistente virtual en su web y por lo tanto ya disfrutan de todos los beneficios que comporta. La clínica especializada en cirugía estética y plástica <a href="http://www.institutodebenito.com/" target="_blank">Instituto de Benito</a>, la productora de refrescos Sunny Delight, la firma de electrónica <a href="http://www.superofertasairis.com/">AIRIS</a>, la propia empresa financiera Credit Services, o el grupo Jubilo Comunicación, son algunos de los clientes que ya ha apostado por dar un salto cualitativo en el servicio y atención al sus clientes en internet.</p>
<p style="text-align:left;"><strong>Más información</strong><br />
<a href="http://www.vi-clone.com/" target="_blank">www.vi-clone.com</a></p>
<p style="text-align:left;">
<p style="text-align:left;">Noticia publicada en <a href="http://www.puromarketing.com">www.puromarketing.com</a> el dia 3 de Julio de 2008.</p>
<p style="text-align:left;">
<p style="text-align:left;">
<p><img src="/DOCUME~1/OSCARF~1/CONFIG~1/Temp/moz-screenshot.jpg" alt="" /></p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[Proyecto de Tésis]]></title>
<link>http://rbermudez.wordpress.com/?p=3</link>
<pubDate>Fri, 04 Jul 2008 04:43:54 +0000</pubDate>
<dc:creator>rbermudez</dc:creator>
<guid>http://rbermudez.wordpress.com/?p=3</guid>
<description><![CDATA[Quiero compartir con ustedes el articulo de intención sobre mi proyecto de tésis.
Artículo de Int]]></description>
<content:encoded><![CDATA[<p>Quiero compartir con ustedes el articulo de intención sobre mi proyecto de tésis.</p>
<p><a href="http://rbermudez.wordpress.com/files/2008/07/961729_articulo-intencion.pdf">Artículo de Intención</a></p>
<p>Se aceptan comentarios, criticas y demás.</p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[Botployees - Just Tell Me How]]></title>
<link>http://alexandrequevedo.wordpress.com/?p=206</link>
<pubDate>Mon, 30 Jun 2008 14:01:44 +0000</pubDate>
<dc:creator>Alexandre Quevedo</dc:creator>
<guid>http://alexandrequevedo.wordpress.com/?p=206</guid>
<description><![CDATA[Conheça a solução
Os Botployees
Um botployee (de robot + employee) é um empregado virtual, que p]]></description>
<content:encoded><![CDATA[<p><em><strong>Conheça a solução</strong></em></p>
<p><strong>Os Botployees</strong></p>
<p>Um botployee (de robot + employee) é um empregado virtual, que possui capacidade para comunicar, cumprir processos e interagir com o computador, com as aplicações e os periféricos nele instaladas ou com a internet. Para comunicar ele escreve e fala. Para cumprir processos ele escuta e lê. Tem capacidade para utilizar vários idiomas nas suas tarefas.<!--more--></p>
<p><strong>Os canais de comunicação</strong></p>
<p>Um botployee é capaz de se comunicar por voz, por SMS, por Skype, por MSN, por email e presencialmente. A execução de processos do botployee é independente do canal de comunicação em utilização. Devido a esta abstração, todos os processos criados ficam imediatamente disponíveis para funcionamento através de qualquer um deles. Isto significa, também, que novos canais de comunicação podem, a qualquer momento, ser integrados, sem afetar o funcionamento do botployee, nem ser necessária qualquer alteração aos processos já existentes.</p>
<p><strong>A Unidade de Processamento Central</strong></p>
<p>O botployee possui uma unidade de processamento central para executar processos e decidir o rumo de cada um. A CPU recebe e envia texto através dos canais de comunicação. A interface de interação permite executar ações sobre outras aplicações existentes, receber eventos ou navegar na web. A gestão dos processos necessários em memória é feita dinâmicamente. Todos os mecanismos de comunicação são assíncronos e thread-safe. Isto permite que o botployee seja imune a quebras inesperadas nos canais de comunicação ou até a possibilidade de criar processos que possam demorar vários meses a serem terminados.</p>
<p><strong>Memória</strong></p>
<p>O botployee tem capacidade para guardar em memória de curto prazo, os dados recolhidos durante os diálogos e utilizar os resultados para gerar querys ou definir interações. Simultâneamente, todos os dados vão sendo acumulados numa memória de longo prazo, que pode ser utilizada para argumentar no presente.<br />
Ao contrário de um humano, o botployee pode armazenar e ter sempre presentes, dados detalhados referentes a vários anos de tarefas.</p>
<p><strong>Interação por SQL</strong></p>
<p>O botployee pode interagir com bancos de dados externos através de querys em SQL. Qualquer dos tipos de bancos de dados mais populares pode ser utilizado através de interfaces nativas de MySQL ou Interbase ou utilizando layers de acesso ADO ou BDE.<br />
O botployee pode gerar um número ilimitado de querys num processo. As querys podem ser parametrizadas pelos dados recolhidos antes, durante ou no final de cada processo.</p>
<p><strong>Interação por machine vision</strong></p>
<p>O botployee tem capacidade para ler a tela do computador e utilizar os resultados nos seus processos. Tal como um utilizador humano ele pode enviar comandos de mouse ou teclado para uma aplicação e ler os resultados desses comandos.</p>
<p>Fonte: <a href="http://www.gruposecrel.com.br/bot_solucao.html" target="_blank">Grupo Secrel</a></p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[Jogar contra um robô]]></title>
<link>http://lugardoconhecimento.wordpress.com/2008/06/25/jogar-contra-um-robo/</link>
<pubDate>Wed, 25 Jun 2008 19:49:02 +0000</pubDate>
<dc:creator>RM</dc:creator>
<guid>http://lugardoconhecimento.wordpress.com/2008/06/25/jogar-contra-um-robo/</guid>
<description><![CDATA[ 


]]></description>
<content:encoded><![CDATA[<p><span style="display:block;width:425px;margin:0 auto;"> [vodpod id=ExternalVideo.613759&#38;w=425&#38;h=350&#38;fv=%26rel%3D0%26border%3D0%26]</p>
<div style="font-size:10px;"><a href="http://vodpod.com/wordpress"></a></div>
<p></span></p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[Você sabia? [1]]]></title>
<link>http://majindox.wordpress.com/?p=93</link>
<pubDate>Tue, 24 Jun 2008 21:35:17 +0000</pubDate>
<dc:creator>Richard</dc:creator>
<guid>http://majindox.wordpress.com/?p=93</guid>
<description><![CDATA[Você sabia que o Haley Joel Osment, o menino do &#8217;Inteligência Artificial&#8217;&#8230;

]]></description>
<content:encoded><![CDATA[<p>Você sabia que o Haley Joel Osment, o menino do 'Inteligência Artificial'...</p>
<p style="text-align:center;"><img class="aligncenter" src="http://www.comciencia.br/resenhas/clonagem/ia01.jpg" alt="" /></p>
<p style="text-align:center;">...E 'O Sexto Sentido' ...</p>
<p style="text-align:center;"><img class="alignnone" src="http://www.adorocinema.com/personalidades/atores/haley-joel-osment/haley-joel-osment02.jpg" alt="" width="364" height="204" /></p>
<p style="text-align:center;">... Era também, o <strong>filho do Forrest Gump</strong>?</p>
<p style="text-align:center;"><img class="alignnone" src="http://content9.flixster.com/question/51/62/57/5162575_ori.gif" alt="" /></p>
<p style="text-align:center;">Quem diria heim, Forrest Gump Jr!</p>
<p style="text-align:center;">...</p>
<p style="text-align:left;"><em>PS. No minimo, intrigante?</em></p>
<p style="text-align:left;"><em>PS2. Nada de post bonito hoje, chega de filosofar um pouco okay?</em></p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[1, 2, 3, Ação!]]></title>
<link>http://raphaelbaldi.wordpress.com/?p=27</link>
<pubDate>Tue, 24 Jun 2008 02:35:18 +0000</pubDate>
<dc:creator>raphaelbaldi</dc:creator>
<guid>http://raphaelbaldi.wordpress.com/?p=27</guid>
<description><![CDATA[Bom gurizada, agora que os trabalhos foram apresentados (são poucos por enquanto, mas têm mais a c]]></description>
<content:encoded><![CDATA[<p>Bom gurizada, agora que os trabalhos foram apresentados (são poucos por enquanto, mas têm mais a caminho) vou começar a postar sobre o que realmente me interessa: <a title="Fórmula 1" href="http://www.formula1.com/" target="_blank">Fórmula 1</a>!</p>
<p>Brincadeira - mas eu gosto mesmo de Fórmula 1. Acho que vou começar falando sobre o que me motivou a escrever, tecendo, em seguida, linhas gerais sobre os assuntos que serão tratados aqui. Falarei, ainda, sobre o que você não encontrará aqui.</p>
<p>Quando pensei em começar um blog tinha algo em mente: dificilmente seria diferente dos inúmeros blogs que existem falando sobre games espalhados na web, até porque os lançamentos são os mesmos, os meus gostos pessoais batem com vários autores e as tecnologias da moda são as mesmas em toda a parte do mundo. Então o que faz esse blog diferente?! Acredito que seja diferente por apresentar a visão de um desenvolvedor, brasileiro, com um ano de experiência em games (jogar não conta como experiência...) e mais de dez anos de experiência em programação e computadores em geral, ou seja, um cara começando no mercado de jogos digitais dentro do Brasil e que, como a maioria dos interessados pelo tema, ainda não sabe bem onde pisar. Isso não basta?! Além disso, faço parte de um dos primeiros times de desenvolvimento de games casuais para a publicidade, isto é, estou próximo de um mercado que parece muito distante dos Gamers Developers em geral - ao longo dos posts verão que não são mercados tão distintos assim.</p>
<p>Mas e vai falar sobre o quê? Bom, a idéia é tentar transmitir algumas de minhas visões a respeito do desenvolvimento de games, as frustrações da área, os desafios e as alegrias que aqueles que pretendem jogar esse jogo enfrentarão e, principalmente, tentar, a partir da minha experiência pessoal, determinar o melhor caminho a seguir. Vou tentar dar o "caminho das pedras" para os iniciantes, pois acredito que um mercado só entra em crescimento se existe competitividade e só existe competitividade quando existem pessoas preparadas oferecendo serviços e produtos semelhantes com preços e qualidades comparáveis. E as pessoas preparadas não surgem do nada. São pessoas como você e eu que têm interesse e estão prontas a dar o sangue para trabalhar com algo formidável como o desenvolvimento de um jogo. É como um filho: te dá muito trabalho pra criar, mas quando cresce te dá muito orgulho.<a href="http://raphaelbaldi.files.wordpress.com/2008/06/dsc03983.jpg"><img class="alignright size-medium wp-image-29" src="http://raphaelbaldi.wordpress.com/files/2008/06/dsc03983.jpg?w=300" alt="A estrada rumo ao mercado de games" width="249" height="187" /></a></p>
<p>Aqui colocarei tudo que sei - e o que descobrir - a respeito da